WordPress CSRF Exploit Draft Status
Asked Answered
T

2

9

How can I best secure WP against a CSRF exploit when creating a new post draft?

If I add a new post and save as draft, I can intercept the request using Burp Suite.

Using the engagement tool in Burp Suite, I can change the value of the post title and paste the URL back in to the browser which creates a new draft with the changed post title.

How can I secure against this?

Cheers

Tricorn answered 25/9, 2018 at 14:9 Comment(8)
Are you using the free or full version of the Burp Suite?Gadid
@magenta Thanks for the reply, the full version allows me to see this issue.Tricorn
Unfortunately, I don't have access to the full version of Burp. For my curiosity's sake can you tell me where and how the exploit URL is being embedded in the WordPress document.Gadid
You should include the full URL you tested, with the actual domain being replaced unless you're ok with sharing it. You could filter the post data and check if there is a post with the same title already created, but I don't think that's a good idea unless you're restricting posts to using unique titles. You could also limit the nonce's lifespan, but WordPress already handling the nonce pretty well.Alluvial
@SallyCJ I cannot share the URL, though the issue can be replicated on any WP install + Burp Suite. I cannot limit the nonce lifespan, as a nonce is not used on the drafts. CheersTricorn
I can't imagine a reliable way to do this. You still have to be authenticated and have a valid nonce to create a post. I'm not sure how else it could be limited, unless you had some throttling plugin installed that wouldn't allow users to submit posts too quickly. What problem this is trying to solve?Application
I agree on all points @incredimike. This issue has cropped up during my penetration testing of WordPress. It's only when creating the draft post, is there a way to add a nonce before the draft is created? CheersTricorn
"Save Draft" absolutely includes, and requires, a valid NONCE to save.... your question is somewhat difficult to answer effectively because you haven't provided a sample $_POST, nor the step(s) by which you are creating the draft....Pawsner
N
6

WordPress already provides a CSRF protection mechanism by using a nonce. When creating a new post, a new unique nonce is created. This nonce is required and must be submitted with the rest of the POST data in order for the post to be saved as a draft or be published. If the nonce is not present or invalid, the request is rejected. (Tested with Wordpress v4.9.8)

In your tests you were able to modify the draft because you submitted the correct nonce using Burp, but in a CSRF attack this value would be unknown. Burp is an intercepting proxy, so you practically performed a MITM attack on your own HTTP traffic. If you're concerned about MITM attacks you should use HTTPS. Of course an attacker could still intercept your network traffic, but all the data would be encrypted.

So, I wouldn't say that this is a CSRF exploit, but a MITM exploit. You can protect your WordPress installation from most public exploits by keeping your WordPress version, plugins and thems updated, and also you can find many security related plugins in https://wordpress.org/plugins/tags/security/.

I think the best tool for security tests on WordPress is WPScan. It has a huge database of vulnerabilities and it can detect possible exploits and enumerate users, version and plugins. WPScan is mostly a recon tool, but we can test if the reported vulnerabilities are exploitable with Metasploit or Wpxf, a less known but powerful tool that is specialized on WordPress exploitation. Note that those tools can only detect and exploit public exploits. If you want to discover new vulnerabilities then you could use Burp or similar scanners and study the WordPress source code.

If I have misunderstood the question, and you have a form that doesn't have a nonce (let's say you're writting a plugin), you can add a nonce with wp_nonce_field and then verify it in the script that receives the form with wp_verify_nonce. However, if you have a WordPress installation that doesn't use a nonce with its forms, you shouldn't try to add a nonce manually, but update to a newer version.

Newton answered 3/10, 2018 at 18:55 Comment(9)
This is not entirely accurate, because WordPress nonces are not expired after a single use properly. It is entirely possible to intercept a nonce, and use it for further requests unimpeded for up to six hours or so by default. This has long been a known exploit in the underlying WordPress nonce implementation that the core team has stubbornly refused to address for several years now.Vigen
WordPress nonces instead of expiring immediately, are advanced through two lifecycle stages, and are bound to individual form actions. Any nonce intercepted can then be used to fulfill multiple calls to the same form action it is bound to, provided its lifecycle steps have not both resolved. This means that without explicitly expiring them, an interceptor can get at least one call to the same form action unimpeded, and multiple calls to the same form action if the source that generated the nonce does not expire them (which a large number of plugins don't, even if they are current).Vigen
@Vigen I agree, and thank you for the very detailed comments, but that would be prevented with the use of HTTPS enforced by HSTS. There is no excuse for not using HTTPS nowadays.Newton
@Vigen Also, if they can intercept the nonce, then they can also get the cookies, so I think this is more of a MITM attack scenario than a CSRF attack. Please correct me if I am wrong, but we are talking about a MITM situation, right?Newton
It would definitely involve at least some MITM, but could then be used for CSRF from pretty much anywhere. If an attacker has successfully snooped the session token cookie and nonce from the page source, they could then resubmit it from basically anywhere, without having to have the original IP signature of the original location.Vigen
This also means that a compromised server can be instructed to send inbound requests to a 3rd party without having to directly intercept the request between the server and client. There are numerous ways to bruteforce shell privileges on a standard wordpress install (such as the lack of executable restriction on the file uploads directory by default, which is shared amongst all users that can upload files/images).Vigen
@Vigen Again, I absolutely agree, but we're no longer talking about a CSRF attack. I think a MITM attack should be the main focus as it is more dangerous. And if we are secured against this attack then a CRSF attack is no longer possible in this case. If they manage to upload a shell, they can do pretty much whatever they want on the site (perhaps on the entire server), but this is a very bad scenario and requires completely different actions.Newton
@Vigen Regardless, I agree that a nonce, by dedinition, should be used only once. I think it's sad that WordPress doesn't have a method to set this value and we have to go through all that trouble, as described in your answer.Newton
I agree also, but I also understand at least in part their reasoning. The WordPress team set out to make a self contained platform that will serve the majority of use cases adequately without rigorous dependencies required to do so. A secure system that is also performant would likely leverage numerous other technologies beyond the grasp of those who are not particularly technically adept. WordPress is a swiss army knife. It does a ton of things but none of them well. A swiss army knife has a saw that fits in your pocket, but it is always inferior to a power saw except for convenience.Vigen
V
4

Wordpress does not use traditional nonces, instead binding them to a specific form action and user session combination, and persisting them for multiple usage over two ticks (default 12 hours each), which means they are by default valid for up to a full day, and may be repeatedly used over that time period, as well as being "refreshed" after a use to reset their time period entirely. This has been consistently criticized for a number of years by security professionals as misleading and insecure, and the WordPress core team has defended their stance by claiming that the requirement that someone has both the user session as well as the actual nonce makes this a negligible threat, although both a compromised host as well as a site that does not have valid ssl protection can make this pretty easy to accomplish.

The underlying issue you are encountering is symptomatic of the fact that a WordPress nonce is not a nonce at all. It is essentially an access control hash used repeatedly for a short duration for a single form action, and has no mechanism in place to insure its single use. This is why you were able to successfully intercept and re-use the nonce. FYI, this behavior can also be recreated pretty easily in Zed Attack Proxy, Wireshark, Charles Proxy, and numerous other similar utilities. Burp is not the only tool that is capable of uncovering this weakness.

You do however have some recourse to correct this if you want, but it is rather involved and not particularly simple to accomplish.

The following functions are pluggable, which means you can override them with your own, and also control the system interpretation of what a nonce is. You will need to provide your own nonce system using these specific methods, and return identical values to the original expected ones so you don't break plugins/core code functionality:

You could, for example, provide your own nonce implementation using a support from a package such as elhardoum/nonce-php or wbswjc/nonce, and then implement it through a custom plugin that overrides the above pluggable functions and uses them as wrappers for your own nonce implementation, although this is not incredibly straightforward and will require a great deal of custom logic to implement.

You will need to not only override the above pluggable functions, but will also need to call apply_filters similarly to their own source, properly nullify whatever changes plugins attempt to make that are bound to those filters, and also return an expected value in the exact same format as the original so you do not disrupt how other plugins/themes you may be using have implemented them.

If you believe that there is sufficient risk, or that the data your site is safeguarding is of sufficient importance, it is likely worth the effort. If you are not handling financial transactions or sensitive data, are properly secured behind ssl, or have no particular interest in writing a custom implementation of nonces and subsequently maintaining it to work around the ways it inevitably breaks numerous plugins who expect the default lax implementation to be present, then you are probably best off taking the core devs at their word and using the defaults, provided you update frequently, have a strong security plugin like wordfence or sucuri, and routinely run updates on all of your plugins/themes.

As an absolute minimum, you pretty much must have SSL in place to mitigate MITM attacks, and should use proper access control headers to mitigate CSRF.

Vigen answered 4/10, 2018 at 19:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.