← All talks

Catching WordPress 0-Days on the Fly

BSides Canberra · 202528:44248 viewsPublished 2025-12Watch on YouTube ↗
Speakers
Tags
About this talk
Ananda Dhakal and Rafie Muhammad present a practical approach to discovering zero-day vulnerabilities in WordPress plugins and themes by monitoring the WordPress SVN repository for dangerous code patterns. The talk covers their custom monitoring tool architecture, real-world vulnerability discoveries including authentication bypasses and arbitrary plugin installation flaws, and discusses challenges like false positives and future improvements.
Show transcript [en]

So today we have Ananda and Rafi uh joining us to speak about catching WordPress zero days on the fly. So thank you very much guys. Take it away. >> Yes. >> Yeah. Uh hello everyone. Uh today we're going to present a talk about catching WordPress zero days on the wild. Uh first uh let us introduce ourselves. Who are we? So we are both from Patch Tech. Uh we do security research on open source especially on CMSS. Currently we work on WordPress, Jumla and Drupals for most of the part. Uh my name is Rafi Muhammad which is a lead security researcher at Patch Tech. And then we have my teammate here Anandra Dakal. We are who are also a security researcher

at Patch Tech. Uh so yeah the the agenda for today is uh first why WordPress and then second one is introduction to WordPress SVN the tool architecture overview real world findings and also the closing to uh the first section is why WordPress I mean why why we want to target WordPress in the first place so yeah WordPress is still uh superior uh in terms of like uh websites it powers 43% of websites in the world uh in the CMS market it it also have a share of 63% at least in the 2024 uh it's also open source of course it's PHP so it's easy to familiarize uh but some of you may be asking why

WordPress again I mean yeah the first uh point is almost every company uh has public facing web which mostly will use a CMS and then WordPress is also like the leading uh CMS market. Uh the second one is WordPress security is quite critical for especially hosting company. So we have a cases of so many companies uh have a concern on WordPress security and on how to protect their websites uh from vulnerabilities especially in WordPress. And the third one uh in case you are wondering uh word WordPress in some cases which might be not as critical as it states uh but yeah it it still can econess initial foothold for attacker to gain like a more privilege to other area

of the company. So yeah me move on to the understanding WordPress ecosystem. So we have three parts of WordPress. The ver the first one is the WordPress core itself which is like the the main app of the WordPress and then we have uh WordPress plugins and themes. Uh currently there are 59K plus number of plugins in the free repository and also 12K plus uh themes in the repository. So everything is hosted on the WordPress SVN uh repository. Next is introduction to WordPress SVN. So if you not familiar with SVN, it's basically like a centralized version of control system for managing coral plugins and teams. So basically it's just git for WordPress ecosystem. Uh this is the example of uh the web

view of the WordPress plug-in SVN. This is one of the most popular plugins in the WordPress which is Elementor which we can use to build like custom widgets uh and models uh for website view. We have uh some endpoints which is stock branches text and also the trunk. So if you're not familiar enough with SVN uh trunk is basically like the main uh branch uh on git and also the text and branch you also have that on git. So we also have WordPress track uh so bug tracking it's for bug tracking and project management uh to to track development and also tickets and also source code change. So basically uh in short sort it's it's a go-to place uh

for a fresh vulnerable code for us to find. Uh this is the example web view of the WordPress track. So you can access it uh for plugins uh plugins.wordpress.org. You can browse all of the text branches and trunks uh for all the plugins and themes on WordPress. So yeah, we move on to the tool architecture overview. So basically uh we just built like a simple script uh for our internal research to do this. So basically first uh we detect a SVN repository uh repository change from WordPress and then we search uh for a quote pattern that could be yield a dangerous process. So we detect some code patterns and also dangerous functions used and if if there

is any uh catch or match and then we we we create an alert uh to our slack. All of this is wrapped under a trading process. So basically we try to execute the script every 1 hour. So every 1 hour usually there is like a maybe like 50 or until hundreds or something change set to the text. So we need to to to implement some trading to catch all of the code change. Uh the first step is uh to track the SVN chains. So we first store the last process SVN revision locally. So reffision is like a state where the plugins or teams uh currently at right now. It's just like a number uh stated

for the revision and then we compare it with the latest version uh with the latest revision available in the WordPress. This is the example uh of the command tool that we use. We use the SVN uh CLI which we use the SVN lock fe and then we compare the self revision with the latest revision that are available on the uh on the WordPress SVN. The results uh mostly will be in XML but it can be also another formats. Uh the next step is to check each of the SVN revision. So for for each revision we extract the plug-in slug. The plug-in slack is basically like a identifying uh strings uh to to make the plugin or team unique

because we have a case where plugin or team have a uh similar names or exact names but it should have like a unique or different uh slack on it and then we get the active installation count of the plugins or team itself. Uh why? Because we only proceed forward with with uh plugins or teams that have five plus uh 5k plus active installation. Why? Because uh for efficiency because previously uh we stated that uh WordPress have like 59k uh number of plugins and also 12k uh teams. So if we check all of the reisions with us without checking the active installation count, it will be uh really hard for the for our uh researcher to check all of them and also

it will be much more false positive on the results. Uh and then for and then we check we check each of the change files on the reisions. First uh we skip the SL text uh SL render SL branch and also SL assets. Why? Because we only we only want to focus on the SL trunk which is like the main branch of the latest code boost. So there is some cases where developer of the plugins push the code directly to the SL text. We don't want to uh we don't want to catch that because maybe they they are only like changing the codes on uh older text or older branches. We only want to check the diff

code on the latest uh term and then we also only process the PHP files because in plugins and teams there is couple of uh file types that can be pushed for example XJS and also HTML. So we only need to check the PHP files. Yeah. And then for each chain set. So ch sets is like a a compilation of code chains in uh SVN revision. So we first open the chet file and then we only process uh added lines or like lines starting with prefix plus. Uh this is the example of the added line uh or fresh code that posted on post on the SPN repostory. So we basically only want to focus on the new code and then uh and

not focus on the code that is being removed with a minus uh prefix. We only detect for the newly added code and after that we search for WordPress and PHP sensitive functions. Uh there are a lot of WordPress or even PHP sensitive functions. Uh this is some of them. So for example, we have a w set out cookie which uh which act like a function to set authentication cookie to users. We also have like the WP insert user where you can where you can create a new user with arbitrary role and we we have a bunch of uh PHP sensitive function. Uh we have a list uh or or at least like the vulnerabilities types of

WordPress in our academic site. You can access it uh with petstack.com/acade academy. Yeah. And if it match uh and then we get the change set link and then we trigger a slack web hook to our slack channel. All right. Now we going to move uh to the findings in the W. This will be presented by Yananda. >> Hello. All right. So basically to summarize what we've done till this point, we're basically tracking the ESPN repository for all the WordPress plugins. So we're tracking all the changes and we're basically looking for sensitive functions and we're uh creating an alert on our Slack if if we find the one of those you know listed sensitive functions uh in the change

log. So uh we did this we we implemented this uh into our Slack and let's move on to some of the findings that we uh that we came across uh in with this tool tooling. So uh starting off with an account takeover vulnerability. So we got this uh uh we got this uh you know the Slack alert um that says like the password policy manager uh with more than 5,000 active installs is using you know those uh WP set o cookie and WP set current users. So uh the code was basically pushed in April 2 and we were able to get uh the alert one day later. So uh looking into the chains lock we

came across something like this. So so basically the air action in it is like an unauthenticated hook uh which you can which you know basically any user can access the the hook. So uh it is hooked with the yamo ppm pass to login reject function. So looking into this function we came across the non-stick that is being done which means uh we looked into like where this nons is being generated and we found that uh the user has to be logged in in order to you know access this nons. So uh even though the hook can be created unauthenticated we would need to be logged in in order to like move forward inside the function. So uh

moving forward with the code the the function is basically taking in a user ID and it is just setting the user. So we basically login as a subscriber or like list privileged user and uh get the nons and what we do is we just supply the uh the you know the user id yamop ppm user ID and then we would be logged in with whatever user ID we supply. So yeah, basically this uh would lead to a complete account takeover of any user we want. So yeah, that was it uh for the account takeover and uh moving on, we've got a PSP object injection. This is a particularly interesting case because uh so this uh this CV, you know, this uh

vulnerability entry uh on WP event plug-in was found and then passed. So uh it was vulnerable till 4.3.6 six and got passed on 4.3.7. And this is how they patched the issue. They basically commented out the vulnerable function. So we're we're not to the Slack Lord point yet. So one day we get this Slack alert uh that says on the the the plugin just pushed a un serialized function into their code. And yeah, we were able to like catch it in like 30 minutes of them pushing the code. And when we look uh when we looked into this function uh we figured out that they removed the comment which is a good thing but as we uh moved across we

found out that they reintroduced the vulnerable code. So basically what happened was uh we reported them the dialization vulnerability they passed it we marked it marked the uh CB as passed and after some time they reintroduced the issue. So yeah, we had to, you know, report it to them again and convince them to fix it and hope that, you know, one day we'll not get the same alert again and they're vulnerable again. So yeah, um, basically for PC was an unauthenticated PC and we do have a gadget chain for WordPress core. So it would link to an RC. So moving on, we've got a arbitrary plug-in installation. So yeah uh this is also a bit you know

interesting case because uh uh you can see that there is unlink and file put content we we got the alert for that uh for that particular case and yeah this this was even less than uh 20 minutes yeah around 23 minutes we we were able to catch this. So uh the interesting part about this is that uh you can see unlink and file boot content were detected by our scanner but this is the vulnerable code and there is no trace of that. So what happened here was that uh the the scanner found the use of those functions but there was vulnerability in a different part of the code. So uh WP AX install requirements uh so if if you're if you're not aware

WP asex hook basically means that any subscriber user or any logged in user would be able to call it and they're just uh you know taking in the slug and they're installing the plug-in uh of whatever we supply uh into the WordPress site. So while it might not sound you know really impactful but there's a catch. So there are a lot of uh you know malicious WordPress plugins like malares that are pushed as well in the WordPress repository. While WordPress uh you know internal security team does their best to remove those from the repository. The catch is that in their ESPN repository those codes still live which means we would be easily able to you know install

those malares and able to you know easily access or get rce. The other way one would exploit this would be uh to get one of the vulnerable plugins with really low installation which is not a big deal at all to find uh you know plugins that have like less than 10 installations surely have pretty you know critical issues. So you just want to uh install that plugin using this and take full access of the WordPress site. So yeah this is what it took to to install any plug-in uh with just you just provide the slug and that's it. So one more case uh is an unauthenticated account takeover. So again we see uh you know WP set o

cookie and set current user that are being uh uh used by the by this plug-in. And when we look at the change log uh we see that uh you know it's basically checking if the user is logged in and if it is it's basically setting the user I'm not sure why they're doing that because the whole point of that function is to like log in and there's no need to check uh if the user is already logged in but that's not the focus. So if the user is not logged in, what they're doing is they're checking for the user ID. And if it's not empty, they're setting that as the user. So what we need to do here is we just need to trace

the user ID parameter and see if we can, you know, somehow populate the value or access the variable. So yeah, so that's what we need to do and this was a pretty complex chain of issues and due to some time constraint uh we're not able to you know add the full code here but you can check the article. So what basically what we did was we we traced it and the function was um the code was added in update card data function which was called by handle value token which was called by the uh post you know rest API request uh post/payu v1 get sipping cost. So we'd have to just pass the user ID in that

post request which would you know eventually flow down the code and uh you know trigger the account takeover. So if you're interested, you can check out the blog as well because it's a bit long, you know, long chain of issues. So yeah, um the last one for for you know the cases is arbitrary file upload. So uh there's uh a a small catch here. The code was pushed in March 21, but we got the alert on April 3. So why did this happen? Uh so you know it's around like 20 or 20 or 20 u 19th of March we stopped getting the alerts and we were like oh developers have suddenly stopped using you know dangerous

functions they are suddenly aware that the risk that they create and we were like uh you know it's been a week and we we still don't see any alerts and we're like okay they are really doing great or everyone suddenly went on a holiday but after 10 days we figured it's a problem of ours. So we had to look up and check that our toollet actually stopped working. So it took us like 12 days to to to catch this issue. So yeah um it's pretty simple. U instead of using like built-in WordPress functions that that is secure by default they decided that they would use their own custom you know uploading functionality without any checks at all. And yeah, but looking

into the function, we found that um it requires edit post permission, which is relatively high. Um it's like uh you need to be at least a contributor user, which is kind of high, but not that high. You know, if you're if you if you write articles for a company, it's normal for you to have a a contributor permission. And if you had that permission, you'd be able to, you know, upload a web shell and get RC. So yeah, that was basically the edited code later on which didn't exist in um previously. So yeah, this request would would basically give you a web shell. You you just need contributor cookies. So moving on, we didn't only see, you

know, vulnerabilities getting introduced uh in the chain set. We we noticed a lot more going on and which we'll get into. So yeah, one day we got this alert and we were like, okay, a lot of includes so there might be some valifi we might catch a couple of them. But when we uh you know when we looked into it, we figured out that they were actually you know patching some already reported vulnerabilities. So not only we got to see like uh you know the vulnerabilities getting introduced, we also got to see them getting passed which is a good thing but a bit sad for us. So uh so we had this u uh alert popping

up but we were not able to check it due to you know being really busy with other stuffs and we checked this alert after like one week and yeah it was vulnerable to CSRF to truncate logs which is not particularly you know severe issue but still it was something that would get a CV ID and when we checked the latest chin lock the feature the the code was removed. So they basically you know introduced the vulnerabilities 4 days before we checked and they patched it 41 hours before we checked. So yeah the life cycle of that issue was really really low. So yeah uh now that we we've we we've uh you know we implemented the the whole

thing we looked into these entries um this is not like u while this is a pretty good um you know starting point to get a get you know really interesting plugins you want to look into because like there are 59,000 plugins right so it it's a mess to select what WordPress plug-in you want to hack on so it while it indeed helped us to you know get initial foothold on what we want to hack or like we're or there were cases where we were just able to you know just open up the chains log and boom that was it. But there are some problems and maybe future works that that's needed for this and the problem the major problem with

with this approach was obviously false positives. So we got a lot of false positives um because of the fact that you know even if you did a simple include with like uh constant value uh which user would not be able to control at all it will still generate an alert. So while it didn't take a long time to you know triage that it took maybe less than 30 seconds to look into those alerts but still the the number of uh you know false positive is a bit concerning and since we're only checking for like specific functions only and we're not like going for the SAS scanning style we we are pretty limited in terms of what

uh what our tool can give us and what uh you know what it can find. So uh in terms of what next or or what we can do to you know get something better or make this even uh better scanning tool uh would be to obviously implement an actual SAS tool there. So it's like basically CI/CD pipelineing the whole WordPress ecosystem. So that that's something we're we're planning on and we'll see if you know how good that works out and yeah so it's the age of AI so we obviously got to you know sprinkle a bit of AI everywhere right so what we're thinking is uh to you know let AI do some of the triaging as well uh which

has not worked particularly well because it's like I mean we we tried with yellows but it's basically summarizing that which takes us nowhere. So but still there are things that we can do u twe tweaking around as well uh to see if we can actually get something. So yeah that is also on our router which we might work on soon. So that's it for the talk. Thank you.

>> Excellent. Thank you very much. And we have plenty of time for questions if anyone's got

>> Hello. Um, by the way, nice talk. So, I have two quick questions. When you say a lot of false positives, can you give us like a rough ratio out of 100 slackers that you get, how much are false positives to true positives? >> Um, maybe around 80% of them are false positives. >> All right. Okay. Yeah. So my second question is like since we are doing a SASbased scan for a well-known uh let's just say ul or whatever wp set user um and I know there's some improvement for AI which can basically check the logic of the code. So let's just say if there's a function um it has a vulnerable code in it but that gets

sanitized later on down the line. So that part can be detected by AI u with the improvements of LLM. The core question I want to ask is like what are you guys doing that the WP or WordPress course team can't do. So like the the process is pretty simple right just search for the SVN's whatever new code change is there scan it up uh using a SAS model and look into it if it's a true positive or false positive. So uh why isn't the WordPress core team doing it uh instead of letting it go in the fly kind of a thing. >> Yeah that's a good question. I think like it would take them like a lot of

resource to actually do that since we paste our full-time job is to like look into WordPress security. So it makes sense for us to do it. But like WordPress internal team is already flooded with a lot of stuffs because so there's this case when we cannot contact a WordPress team, right? So we forward it to WordPress internal team. So they're already flooded with even with just that. So they don't have a lot of resource and yeah maybe that's not their number one priority as well. They they mostly focus on core stuffs. So that's why they might not want to allocate a lot of resources into that. >> All right. And one last question sorry. So how good has been with WordPress core

team the CV process like just if you find something uh how good has been it been till till it goes to triage and you get a CV assigned. I have seen a lot of people complaining with WordPress that we do find an issue but mostly the WordPress core team comes and say like hey the developer has stopped maintaining it so you won't be assigned a CV for it because it won't be patched one way that's the I don't I don't think there's much logic to it but that's what I heard on the social media or at least try to pull off it >> I mean we do assign CVS even if the plug-in is abandoned so I'm not sure

maybe they're at the wrong this.

>> Yeah. Hi. >> Um, so obviously there's a point in time where you started monitoring, right? And everything before that will not show up in your alerts. Is there any idea that you might have to apply what you're doing here to already existing vulnerabilities? >> Uh, sorry I didn't give you a question. So like you're alerting on anything which is being committed any new commits into SPF >> but everything before you started monitoring will that's already vulnerable will already be still be vulnerable now if they're not changing it if it's not being updated >> so like is there any way to for you to look back at past commits that sort of thing? >> Yeah.

>> And like is that something you're looking at doing? >> Yeah. Yeah, I mean it's possible to go way go all the way back because everything is in the SPN but I do not think it would be a very you know efficient way because over the time a lot of vulnerabilities have been have been reported in in WordPress ecosystem recently in the last two or three years due to you know bug bounties and everything uh for WordPress and yeah I mean uh given that there are a lot of false positives and there are already enough you know commits going on around in the recent is I don't think you know we we will ever have a time to you know

go back in time and like scan all those previous issues as well. >> Yeah, fair enough. >> Anybody else? Excellent. Thank you. Hands together again.