rapid7 / metasploit-framework

Metasploit Framework
https://www.metasploit.com/
Other
33.03k stars 13.74k forks source link

Add WordPress XMLRPC Massive Bruteforce #6226

Closed KINGSABRI closed 8 years ago

KINGSABRI commented 8 years ago
KINGSABRI commented 8 years ago

A new pull request has been created due creating PR from a new branch :)

The original pull request is #6209

KINGSABRI commented 8 years ago

Is there any observations here to fix?

@wchen-r7 Thanks for make things clear to me here

wchen-r7 commented 8 years ago

@KINGSABRI I think one of the things to do here is to convert this module to a LoginScanner. Like what wordpress_xmlrpc_login does, but you can replace that completely because yours is smarter and faster. I personally don't see the point of having both.

We have some wiki docs about how to write a LoginScanner module. For you, you can start with step 3 in this wiki: https://github.com/rapid7/metasploit-framework/wiki/How-to-write-a-HTTP-LoginScanner-Module

Other docs you can read: https://github.com/rapid7/metasploit-framework/wiki/Creating-Metasploit-Framework-LoginScanners

And then of course, you can use wordpress_xmlrpc_login as a reference: https://github.com/rapid7/metasploit-framework/blob/master/modules/auxiliary/scanner/http/wordpress_xmlrpc_login.rb

https://github.com/rapid7/metasploit-framework/blob/master/lib/metasploit/framework/login_scanner/wordpress_rpc.rb

You will see that the auxiliary module part is just passing arguments and parsing results. The actual login code is in lib/metasploit/framework/login_scanner/wordpress_rpc.rb.

Note that the Metasploit::Framework::LoginScanner::WordpressRPC class is on top of Metasploit::Framework::LoginScanner::HTTP, so you probably wanna look at the HTTP class too to see what methods you can use: https://github.com/rapid7/metasploit-framework/blob/master/lib/metasploit/framework/login_scanner/http.rb

Hope this helps.

jhart-r7 commented 8 years ago

One suggestion related to @wchen-r7's comment -- I agree on the lack of a need for two separate modules that do nearly the same thing, but I think it would be nice to have the option to have the slower option available should your situation require it. I only looked at the code briefly, but I could see this being implemented by offering a CHUNKSIZE option which when set to 0 or anything about that ~1500-1700 threshold, you send as many logins as you can at once, and with any value in between, you try that many. That way, a user could set CHUNKSIZE 1 and get the same low and slow but easily detectable attack. My $0.02.

wchen-r7 commented 8 years ago

Yeah, adjustable speed would be a nice thing to have :+1:

KINGSABRI commented 8 years ago

That's really encouraging!.

@wchen-r7 I tried to build it as LoginScanner as I saw in wordpress_xmlrpc_login module put I really got confused since I need the user and password lists as arrays to play around them but it wasn't clear how to do so through Metasploit::Framework::CredentialCollection and Metasploit::Framework::LoginScanner::WordpressRPC so I missed some flixability there (because of lake of my knowledge of these modules)

That's why I didn't do it that way, I need to take control of arrays, requests and responses

@jhart-r7 I like your idea, I'll add CHUNKSIZE as user configurable right now, it's more elegant too

Thanks guys for your support!

wchen-r7 commented 8 years ago

@KINGSABRI Yeah I understand. I will try to help you. I will try to submit a pull request to you sometime this or next week. If you don't wanna wait, feel free to ask me anything and we will try to help you get there. You are doing great so far :-)

KINGSABRI commented 8 years ago

I'll try to understand that modules more and see more examples then I'll feed you back. Hopefully I can make it LoginScanner with elegant code.

In the meantime, should be we keep this issue open (and keep pushing to it) or what do you advice?

@wchen-r7 appreciated man!

wchen-r7 commented 8 years ago

You're welcome.

Yeah we can keep the PR open :-) I'll add the Delayed label so people know we are still working on it :-)

firefart commented 8 years ago

I would love to test this one on some of my targets :P

KINGSABRI commented 8 years ago

@FireFart I would love to hear a w00t from you using it! ;)

In a legal way of course ;P

wchen-r7 commented 8 years ago

Sorry for the delay. I am still working on it.... need to change the way loginscanner gives me creds to match what this module is doing...

wchen-r7 commented 8 years ago

PR sent to https://github.com/KINGSABRI/metasploit-framework/pull/1

KINGSABRI commented 8 years ago

Ohh, I'm sorry for delay @wchen-r7 , I didn't notice the PR :(

ok I'm getting the following error

msf auxiliary(wordpress_xmlrpc_login) > run

[*] 172.17.0.3:80 WORDPRESS_XMLRPC - status!
[*] Target 172.17.0.3:80 is running Wordpress
[*] XMLRPC enabled, Hello message received!
[*] 172.17.0.3:80 - Starting XML-RPC login sweep...
[-] Auxiliary failed: NoMethodError undefined method `compile' for #<Rex::Proto::Http::Response:0x005646293d5228>
Did you mean?  completed?
[-] Call stack:
[-]   /usr/local/lib/ruby/gems/2.3.0/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:369:in `__define_callbacks'
[-]   /usr/local/lib/ruby/gems/2.3.0/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:79:in `run_callbacks'
[-]   /usr/local/lib/ruby/gems/2.3.0/gems/activemodel-4.0.13/lib/active_model/validations.rb:373:in `run_validations!'
[-]   /usr/local/lib/ruby/gems/2.3.0/gems/activemodel-4.0.13/lib/active_model/validations.rb:314:in `valid?'
[-]   /home/KING/Code/MSF/metasploit-framework/lib/metasploit/framework/login_scanner/base.rb:248:in `valid!'
[-]   /home/KING/Code/MSF/metasploit-framework/lib/metasploit/framework/login_scanner/base.rb:194:in `scan!'
[-]   /home/KING/Code/MSF/metasploit-framework/modules/auxiliary/scanner/http/wordpress_xmlrpc_login.rb:107:in `run_host'
[-]   /home/KING/Code/MSF/metasploit-framework/lib/msf/core/auxiliary/scanner.rb:116:in `block (2 levels) in run'
[-]   /home/KING/Code/MSF/metasploit-framework/lib/msf/core/thread_manager.rb:100:in `block in spawn'
[*] Auxiliary module execution completed
msf auxiliary(wordpress_xmlrpc_login) > 
wchen-r7 commented 8 years ago

@KINGSABRI Hmmm that is interesting. I have actually never seen that error before. It looks like the error occurs in the valid! call... not sure why. I will look into it. Thanks!

wchen-r7 commented 8 years ago

@KINGSABRI I am not able to reproduce this problem:

msf auxiliary(wordpress_xmlrpc_login) > run

[*] 192.168.1.123:80:/wordpress/xmlrpc.php - Sending Hello...
[+] XMLRPC enabled, Hello message received!
[*] 192.168.1.123:80 - Starting XML-RPC login sweep...
[+] 192.168.1.123:80 WORDPRESS_XMLRPC - Success: 'admin:goodpassword'
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf auxiliary(wordpress_xmlrpc_login) >

Travis keeps failing too, but I don't actually get any of that locally:

Finished in 2 minutes 25.8 seconds (files took 9.35 seconds to load)
11057 examples, 0 failures, 34 pending

@KINGSABRI could you please do this?

$ git checkout upstream-master
$ git pull
$ git checkout wordpress_xmlrpc_massive_bruteforce
$ git checkout -b test_wordpress
$ git merge upstream-master

Note: You might not have a "upstream-master" branch, but this is supposed to be your master branch that is sync'd with the latest commit from metasploit-framework.

And then test your Wordpress login module again? Do you still get that exception? Thanks.

brandonprry commented 8 years ago

It actually fails locally exactly as it does for him. I pulled latest upstream master, branched, merged in his branch, then began working on it and received the error.

brandonprry commented 8 years ago
msf auxiliary(wordpress_xmlrpc_login) > run

[*] 192.168.0.19:80 WORDPRESS_XMLRPC - status!
[*] Target 192.168.0.19:80 is running Wordpress
[*] XMLRPC enabled, Hello message received!
[*] 192.168.0.19:80 - Starting XML-RPC login sweep...
[-] Auxiliary failed: NoMethodError undefined method `compile' for #<Rex::Proto::Http::Response:0x007fabd10f4b30>
[-] Call stack:
[-]   /Users/bperry/.rvm/gems/ruby-2.1.6/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:369:in `__define_callbacks'
[-]   /Users/bperry/.rvm/gems/ruby-2.1.6/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:79:in `run_callbacks'
[-]   /Users/bperry/.rvm/gems/ruby-2.1.6/gems/activemodel-4.0.13/lib/active_model/validations.rb:373:in `run_validations!'
[-]   /Users/bperry/.rvm/gems/ruby-2.1.6/gems/activemodel-4.0.13/lib/active_model/validations.rb:314:in `valid?'
[-]   /Users/bperry/projects/metasploit-framework/lib/metasploit/framework/login_scanner/base.rb:248:in `valid!'
[-]   /Users/bperry/projects/metasploit-framework/lib/metasploit/framework/login_scanner/base.rb:194:in `scan!'
[-]   /Users/bperry/projects/metasploit-framework/modules/auxiliary/scanner/http/wordpress_xmlrpc_login.rb:107:in `run_host'
[-]   /Users/bperry/projects/metasploit-framework/lib/msf/core/auxiliary/scanner.rb:116:in `block (2 levels) in run'
[-]   /Users/bperry/projects/metasploit-framework/lib/msf/core/thread_manager.rb:100:in `call'
[-]   /Users/bperry/projects/metasploit-framework/lib/msf/core/thread_manager.rb:100:in `block in spawn'
[*] Auxiliary module execution completed
msf auxiliary(wordpress_xmlrpc_login) > 
wchen-r7 commented 8 years ago

@brandonprry Did you do: rake spec?

brandonprry commented 8 years ago

I did not, let me do that.

brandonprry commented 8 years ago

rake spec:

Brandons-iMac:metasploit-framework bperry$ rake spec
rake aborted!
TypeError: no implicit conversion of nil into String
/Users/bperry/.rvm/gems/ruby-2.1.6/gems/railties-4.0.13/lib/rails/paths.rb:189:in `expand_path'
/Users/bperry/.rvm/gems/ruby-2.1.6/gems/railties-4.0.13/lib/rails/paths.rb:189:in `block in expanded'
/Users/bperry/.rvm/gems/ruby-2.1.6/gems/railties-4.0.13/lib/rails/paths.rb:163:in `each'
/Users/bperry/.rvm/gems/ruby-2.1.6/gems/railties-4.0.13/lib/rails/paths.rb:163:in `each'
/Users/bperry/.rvm/gems/ruby-2.1.6/gems/railties-4.0.13/lib/rails/paths.rb:188:in `expanded'
/Users/bperry/.rvm/gems/ruby-2.1.6/gems/railties-4.0.13/lib/rails/paths.rb:139:in `first'
/Users/bperry/projects/metasploit-framework/lib/metasploit/framework/require.rb:52:in `optionally_active_record_railtie'
/Users/bperry/projects/metasploit-framework/Rakefile:10:in `<top (required)>'
/Users/bperry/.rvm/gems/ruby-2.1.6/bin/ruby_executable_hooks:15:in `eval'
/Users/bperry/.rvm/gems/ruby-2.1.6/bin/ruby_executable_hooks:15:in `<main>'
(See full trace by running task with --trace)
Brandons-iMac:metasploit-framework bperry$
brandonprry commented 8 years ago

I can hop on IRC if you want to try and dig into this, am available to help figure it out

brandonprry commented 8 years ago

My local might be messed up. Checking out upstream master results in the same spec failure. Looking to fix.

firefart commented 8 years ago

@brandonprry the rspec error is due to a missing database connection. You need a working db connection for rspec to work (I once opened an issue for this, but it looks like it's a requirement now)

brandonprry commented 8 years ago

Bah, I see. OK.

brandonprry commented 8 years ago

I wiped my framework directory, recloned, branched, then merged in kingsabri's code, can reproduce still.

For me, it only breaks when it has successfully found an XMLRPC instance.

msf auxiliary(wordpress_xmlrpc_login) > run

[*] 192.168.0.0:80 WORDPRESS_XMLRPC - status!
[-] 192.168.0.0:80:80/wordpress does not appear to be running Wordpress or you got blocked! (Do Manual Check)
[-] XMLRPC is not enabled! Aborting
[*] 192.168.0.1:80 WORDPRESS_XMLRPC - status!
[-] 192.168.0.1:80:80/wordpress does not appear to be running Wordpress or you got blocked! (Do Manual Check)
[-] XMLRPC is not enabled! Aborting
[*] 192.168.0.2:80 WORDPRESS_XMLRPC - status!
[-] 192.168.0.2:80:80/wordpress does not appear to be running Wordpress or you got blocked! (Do Manual Check)
[-] XMLRPC is not enabled! Aborting
[ ... SNIP ... ]
[*] 192.168.0.18:80 WORDPRESS_XMLRPC - status!
[-] 192.168.0.18:80:80/wordpress does not appear to be running Wordpress or you got blocked! (Do Manual Check)
[-] XMLRPC is not enabled! Aborting
[*] 192.168.0.19:80 WORDPRESS_XMLRPC - status!
[*] Target 192.168.0.19:80 is running Wordpress
[*] XMLRPC enabled, Hello message received!
[*] 192.168.0.19:80 - Starting XML-RPC login sweep...
[-] Auxiliary failed: NoMethodError undefined method `compile' for #<Rex::Proto::Http::Response:0x007feb30ed4e00>
[-] Call stack:
[-]   /Users/bperry/.rvm/gems/ruby-2.1.6/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:369:in `__define_callbacks'
[-]   /Users/bperry/.rvm/gems/ruby-2.1.6/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:79:in `run_callbacks'
[-]   /Users/bperry/.rvm/gems/ruby-2.1.6/gems/activemodel-4.0.13/lib/active_model/validations.rb:373:in `run_validations!'
[-]   /Users/bperry/.rvm/gems/ruby-2.1.6/gems/activemodel-4.0.13/lib/active_model/validations.rb:314:in `valid?'
[-]   /Users/bperry/projects/metasploit-framework/lib/metasploit/framework/login_scanner/base.rb:248:in `valid!'
[-]   /Users/bperry/projects/metasploit-framework/lib/metasploit/framework/login_scanner/base.rb:194:in `scan!'
[-]   /Users/bperry/projects/metasploit-framework/modules/auxiliary/scanner/http/wordpress_xmlrpc_login.rb:107:in `run_host'
[-]   /Users/bperry/projects/metasploit-framework/lib/msf/core/auxiliary/scanner.rb:116:in `block (2 levels) in run'
[-]   /Users/bperry/projects/metasploit-framework/lib/msf/core/thread_manager.rb:100:in `call'
[-]   /Users/bperry/projects/metasploit-framework/lib/msf/core/thread_manager.rb:100:in `block in spawn'
[*] Auxiliary module execution completed
msf auxiliary(wordpress_xmlrpc_login) > 
KINGSABRI commented 8 years ago

Same as @brandonprry error here

msf auxiliary(wordpress_xmlrpc_login) > run

[*] 172.17.0.3:80 WORDPRESS_XMLRPC - status!
[*] Target 172.17.0.3:80 is running Wordpress
[*] XMLRPC enabled, Hello message received!
[*] 172.17.0.3:80 - Starting XML-RPC login sweep...
[-] Auxiliary failed: NoMethodError undefined method `compile' for #<Rex::Proto::Http::Response:0x007feaa58fa8f8>
Did you mean?  completed?
[-] Call stack:
[-]   /usr/local/lib/ruby/gems/2.3.0/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:369:in `__define_callbacks'
[-]   /usr/local/lib/ruby/gems/2.3.0/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:79:in `run_callbacks'
[-]   /usr/local/lib/ruby/gems/2.3.0/gems/activemodel-4.0.13/lib/active_model/validations.rb:373:in `run_validations!'
[-]   /usr/local/lib/ruby/gems/2.3.0/gems/activemodel-4.0.13/lib/active_model/validations.rb:314:in `valid?'
[-]   /home/KING/Code/MSF/metasploit-framework/lib/metasploit/framework/login_scanner/base.rb:248:in `valid!'
[-]   /home/KING/Code/MSF/metasploit-framework/lib/metasploit/framework/login_scanner/base.rb:194:in `scan!'
[-]   /home/KING/Code/MSF/metasploit-framework/modules/auxiliary/scanner/http/wordpress_xmlrpc_login.rb:107:in `run_host'
[-]   /home/KING/Code/MSF/metasploit-framework/lib/msf/core/auxiliary/scanner.rb:116:in `block (2 levels) in run'
[-]   /home/KING/Code/MSF/metasploit-framework/lib/msf/core/thread_manager.rb:100:in `block in spawn'
[*] Auxiliary module execution completed

Thanks!

wchen-r7 commented 8 years ago

@brandonprry For testing purposes, did you merge from the latest master to your wordpress branch?

brandonprry commented 8 years ago

Yes, I merged latest master into my formed master before branching to merge in kingsabri's code.

The commit I have before merging in kingsabri's code is:

$ git log | head -n30
commit a03017957717ba97576fd26c0db55cac3e51875c
Author: Metasploit <metasploit@rapid7.com>
Date:   Fri Jan 15 15:17:13 2016 -0800

    Bump version of framework to 4.11.8
firefart commented 8 years ago

@brandonprry @wchen-r7 I created a PR for the rspec issue so it's more clear https://github.com/rapid7/metasploit-framework/pull/6484.

The error looks like we are passing a res instead of a res.body somewhere in the code

wchen-r7 commented 8 years ago

@brandonprry @KINGSABRI I am finally seeing this error now... ok looking into it.

brandonprry commented 8 years ago

In testing this, it looks like this was partially mitigated between 4.3.2 and 4.4.1.

In 4.4.1, if the first command you specify has invalid credentials, even if the second command has correct creds, it will report an authentication failure.

In 4.3.2, I do not see this behaviour and the authentication is performed as expected across each method sent in the system.multicall request.

Just FYI for testing. I would love to see someone confirm this.

wchen-r7 commented 8 years ago

If I remove valid! then it works fine...... but it shouldn't be removed :-/

wchen-r7 commented 8 years ago

Well guys, I am able to tell the problem is caused by my bad code in Metasploit::Framework::LoginScanner::WordpressRPC... sorry about that, I will try to figure out and fix it.

So @KINGSABRI, expect a patch from me... hopefully soon.

wchen-r7 commented 8 years ago

Hi @KINGSABRI, I have submitted another PR to your branch, hopefully that solves the problem: https://github.com/KINGSABRI/metasploit-framework/pull/2

KINGSABRI commented 8 years ago

Thanks @wchen-r7 it works very well!, however, the script doesn't iterate over all password list, it takes the very first password only. As you can see below, STOP_ON_SUCCESS is false

msf auxiliary(wordpress_xmlrpc_login) > show options 

Module options (auxiliary/scanner/http/wordpress_xmlrpc_login):

   Name              Current Setting                                                                 Required  Description
   ----              ---------------                                                                 --------  -----------
   BLOCKEDWAIT       6                                                                               yes       Time(minutes) to wait if got blocked
   BRUTEFORCE_SPEED  5                                                                               yes       How fast to bruteforce, from 0 to 5
   CHUNKSIZE         1500                                                                            yes       Number of passwords need to be sent per request. (1700 is the max)
   DB_ALL_CREDS      false                                                                           no        Try each user/password couple stored in the current database
   DB_ALL_PASS       false                                                                           no        Add all passwords in the current database to the list
   DB_ALL_USERS      false                                                                           no        Add all users in the current database to the list
   PASS_FILE         /home/KING/Code/MSF/metasploit-framework/data/wordlists/http_default_pass.txt   no        File containing passwords, one per line
   Proxies                                                                                           no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS            172.17.0.3                                                                      yes       The target address range or CIDR identifier
   RPORT             80                                                                              yes       The target port
   STOP_ON_SUCCESS   false                                                                           yes       Stop guessing when a credential works for a host
   TARGETURI         /                                                                               yes       The base path to the wordpress application
   THREADS           1                                                                               yes       The number of concurrent threads
   USERNAME                                                                                          no        A specific username to authenticate as
   USER_FILE         /home/KING/Code/MSF/metasploit-framework/data/wordlists/http_default_users.txt  no        File containing usernames, one per line
   VERBOSE           true                                                                            yes       Whether to print output for all attempts
   VHOST                                                                                             no        HTTP server virtual host

msf auxiliary(wordpress_xmlrpc_login) > run

[*] 172.17.0.3:80 WORDPRESS_XMLRPC - status!
[*] Target 172.17.0.3:80 is running Wordpress, XMLRPC is enabled!
[*] 172.17.0.3:80 - Starting XML-RPC login sweep...
[+] 172.17.0.3:80 WORDPRESS_XMLRPC - SUCCESSFUL: admin:admin
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf auxiliary(wordpress_xmlrpc_login) > 
KINGSABRI commented 8 years ago

Ok, that's really confusing ;/

I've a some users on my docker wrodpress

admin, root, system, user

I'm really confused

wchen-r7 commented 8 years ago

if the first user is correct and the correct password is the first password, it finds the password and go to other users

Yes, this is the expected behavior. Normally each account should only have one password, so even though you set STOP_ON_SUCCESS to false, once that password is found, the account will not be tried again.

if the other users have the same password (the first password), it finds i, if not the first password, it doesn't find it!

hmmmm..... I will have to try this in a bit.

if the first user's password is not the first password, the script doesn't find his password and the other users as well

So in this test, I have 4 accounts. The first one is correct, the other 3 are not:

screen shot 2016-01-19 at 11 39 01 pm

And then I put the correct password for the first account in the middle of the password list:

screen shot 2016-01-19 at 11 39 42 pm

And the module is able to find the correct password for that user:

screen shot 2016-01-19 at 11 40 36 pm

Could you please double check this scenario? Thanks!

KINGSABRI commented 8 years ago

please try to bruteforce more than one user

and it works for you but it didn't for me My case is

If the user exists and the password is not at the top of the password list, the script can't find the password Note: I'm using the default msf lists and I've admin:password credentials and the password word is the second password in the list and it fails to get it

something missing in the iteration :(

brandonprry commented 8 years ago

Like I said, the default XMLRPC behaviour has been mitigated in 4.4.1. The behaviour kingsabri is describing is exactly this mitigation. It is not a problem with the code or with Metasploit.

Download 4.3.2, set up the same users, then run the bruteforce module again and you will see that all of your users, regardless of where they are in the XML, will be able to have the username/password bruteforced.

wchen-r7 commented 8 years ago

Should there be a version check or some sort to prevent the module from running against Wordpress with that mitigation? It seems to make bruteforcing difficult to a point it's not so effective?

brandonprry commented 8 years ago

Right, the mitigation essentially neuters any way to use the system.multicall to be useful for massive bruteforcing, you can only test a single username/password pair with it, which doesn't buy you much.

I think a version check is likely a good idea. Should be easy enough, right @FireFart?

brandonprry commented 8 years ago

That being said, I don't know exactly when this mitigation was introduced.

KINGSABRI commented 8 years ago

@brandonprry that's sad I'll try to find an easy way to install an older version on docker since I'm using the official which install the latest version yet

wchen-r7 commented 8 years ago

@KINGSABRI Another quick PR for you for the version check: https://github.com/KINGSABRI/metasploit-framework/pull/3

KINGSABRI commented 8 years ago

Great, it's working fine now

wchen-r7 commented 8 years ago

Thank you! I will continue improving this. It looks like I still need to make sure the options are taken care of, and rspec. I will try to send another PR in a day or two :-)

KINGSABRI commented 8 years ago

Enhanced password method for reading huge password, making it lazy speeds it up to 2.97x times faster for a 1.2G password file

wchen-r7 commented 8 years ago

:+1:

wchen-r7 commented 8 years ago

@KINGSABRI Quick question for you. There are other datastore options that are used as password sources, such as: PASSWORD, USERPASS_FILE, USER_AS_PASS, DB_ALL_CREDS, and DB_ALL_PASS... do you actually want to skip supporting them and only allow PASS_FILE, or you think we should do those too?