Welcome back to the Patchstack Weekly security update! This update is for week 19 of 2022 and is about secure AJAX endpoints and WordPress vulnerabilities.
This week in vulnerability news, I will share two WordPress plugins with security bugs that have no patch available.
One could lead to tricking logged-in users to run arbitrary code on websites, and the other could lead to unauthenticated SQL injection.
And I have a bit of breaking news to add, it was just reported by Portswigger that it appears WordPress websites with incomplete installations are being targeted shortly after being set up.
In this week’s knowledge share, I will talk about securing WordPress AJAX endpoints.
Why it is important to secure AJAX endpoints? How to spot which functions need more attention from secure code review, and how to do security testing with a tool I guarantee you probably already have installed.
I will share this tool’s information in the weekly knowledge share.
Vulnerability news
Portswigger reported on May 6th, that WordPress websites with incomplete installations are being targeted by attackers, who will complete the installation and then go on to install some backdoors of their own.
It is being reported that the attackers are utilizing public information available when the website’s TLS certificate is created.
They check the newly created website, and if they get to the WordPress installation wizard before the site owner does, then they will take over the website.
This is a valid concern, however, most managed WordPress hosting providers will handle the installation process for the user, so their websites are not at risk.
If, however, when you are setting up a new WordPress website and your hosting provider still uses the manual WordPress installation process, then your best bet would be to ensure you finish that installation process immediately.
WP Contacts Manager <= 2.2.4 – Unauthenticated SQL Injection (SQLi)
The WP Contacts Manager plugin unfortunately has an unpatched security bug at this time.
This bug is now public, originally reported by Cydave of Cyllective. It appears that the plugin has been closed by the WP.org plugins team since April 20th, likely due to this issue.
Users may wish to look for an alternative plugin or reach out to the developer to see if they are aware of the issue and ask if they are working on a patch or not.
Code Snippets Extended plugin <= 1.4.7 – Cross-Site Request Forgery (CSRF) leading to Remote Code Execution (RCE)
The code snippets extended plugin, which has features like adding code chunks or snippets in your pages, unfortunately, is affected by a CSRF security bug.
This security bug was reported by Rasi Afeef of the Patchstack Alliance. It appears this bug could lead to arbitrary code execution if an attack is successful (which would require tricking currently logged-in users to follow malicious links to perform the attack).
There is no patch available through the WP.org repository at this time, but I see the developer is actively working on the issue and has provided a temporary patch via GitHub until they can get their updates onto the WP.org repository.
This is pretty awesome of the developer, I can tell they are working hard and trying to get the patch available to their users even if they have to work around some obstacles.
Hopefully, the patch is made public on WP.org soon. This is important so the auto-update functionality within WordPress core can do its thing.
In the meantime, you may wish to be extra careful if any of your websites use the code snippets extended plugin. Since CSRF requires interaction with a logged-in user, a temporary workaround would be to tell users to manually click the “log out” link in wp-admin, when they are done performing tasks on the website.
Weekly knowledge
Secure AJAX endpoints
AJAX endpoints are everywhere, they decouple the data and presentation layers empowering web applications to run asynchronously. This was a fancy way to say it, but AJAX endpoints allow the web page’s content to be dynamically updated from data sources after the page has been loaded and presented to the browser.
This speeds up the responsiveness of the web application significantly because the data on the page can be updated/modified/etc.. without the need to re-load the whole page every time the user interacts with it.
AJAX is a valuable web application development technology and a very popular way to develop web applications nowadays. So, let’s talk about some security considerations you should think about when adding new secure AJAX endpoints to a WordPress website.
Authenticated or not
It is easy to create a new AJAX endpoint in WordPress. Simple use the add_action() function, with:
- The first argument (the hook name) name starting with either: wp_ajax_{action} or wp_ajax_nopriv_{action};
- and the second argument is the function name in PHP you would like to call every time this AJAX endpoint is called. The value of {action} will be the AJAX action name.
The two hook name options wp_ajax_{action} and wp_ajax_nopriv_{action} have one big difference.
With wp_ajax_{action}, the endpoint will only work if the user is logged in. With wp_ajax_nopriv_{action}, then the endpoint will be available to everyone, logged in or not.
This brings me to the first and most important tip:
If you create a wp_ajax_nopriv endpoint, you need to be certain that the function you call will not return sensitive data or take privileged action on the website.
Failure to do this could open up an unauthenticated attack vector. Be sure all nopriv AJAX endpoints you create have calls to functions that are defensively coded to the best of your ability, and do not expose an unauthenticated vulnerability.
This settles the nopriv concern, but what about the authenticated wp_ajax_{action} calls?
Authorization and nonces
Once your unauthenticated (wp_ajax_nopriv_{action}) endpoints are secure, you will want to make sure your authenticated (wp_ajax_{action}) endpoints have proper authorization checks and nonces.
Remember, authentication is not authorization and authenticated endpoints only check if the user is logged in, this means any user on the website (including subscribers) can make requests to this endpoint.
So you will want to be sure to add:
- Authorization checks via current_user_can()
- Nonce check to prevent CSRF
I have discussed the details on how to do both of these in prior Patchstack Weekly episodes, specifically in the episode about Authentication vs. Authorization and I spoke about nonces when I talked about protecting against CSRF.
Testing and attacking endpoints
If you are the type of person who learns by doing, and would like to test out how to poke and prod your web application’s AJAX endpoints, then you’re in luck!
I have a few tips on how you can test your AJAX endpoints using a tool you already have: a browser, specifically, your browser’s developers toolkit.
Most browsers have a developer toolkit, opening the toolkit may vary between browsers but multiple browsers can easily open their developers’ toolkit via a right-click and choose “Inspect” or simply pressing the F12 key.
Once open, you can go to the Javascript console and user the jQuery.post function, to hit the website’s AJAX user pretty easily.
jQuery.post(ajax_object.ajax_url, data, function(response) {
alert('Server Response: ' + response);
});
This is useful if you are very familiar with the names of your AJAX endpoint actions, and the arguments they expect.
If you are not familiar with the codebase you’re looking at (like many bug bounty hunters), then you will need to do some discovery to identify those endpoints and look at their requests. Luckily, this can also be done in your browser.
Under the “Network” tab in your browser’s developer toolkit. It will give you tons of useful data about every HTTP request your browser is making.
Here is how I use it:
Once the Network tab is open I recommend you enable Persistent mode, this is not required but helpful so you can see a record of all requests.
Now, browse your web application, specifically use the plugin’s features and forms, submit data into every form or page you think may trigger an AJAX request, and basically use every functionality you can find.
After browsing, you will notice your Network tab history will be full of requests. You can filter these out to only view the requests to /wp-admin/admin-ajax.php.
Find one of those AJAX requests you want to learn more about, click on it and you will see full details about the HTTP request, response, cookies, etc…
If you would like to do some testing, right-click the request in the Network tab and you should see something like an “Edit and Resend” option.
Choose that, and a pop-up dialog will appear. You can use this dialog to edit the HTTP request to anything you would like, and send it to the web application just like a new request.
If you send an attack payload successfully, congratulations, you’re doing bug bounty hunting.
These are some ways you can test your AJAX endpoints using a tool you already have. Your browser.
You can go further than this though, use a tool like OWASP ZAP (which, by the way, is open source, and has a community behind it as well!).
OWASP ZAP can help developers with automating security testing, it was designed for this purpose. Some day, I’ll share with you some ZAP tips, but it will have to wait for another week, as I am out of time!
Thanks and appreciation
This week’s thanks go out to Cydave of Cyllective for identifying that unpatched issue in the WP Contacts Manager plugin. As well as an extra thank you to Rasi Afeef of the Patchstack Alliance for reporting the security bug in Code Snippets Extended.
A special thank you is extended to the developer of the Code Snippets plugin, Shea Bunge. I see you are actively working on a patch for a Reflected XSS issue, making it available immediately for users who need it now, and are putting in a ton of extra effort to address the security bug. Great job showing everyone what it means to be an open-source developer worthy of our trust.
I will be back next week with more security tips, tricks, opinions, and news on the Patchstack Weekly security update!