I found a Stored Cross Site Scripting vulnerability in WordPress that got rejected and got labeled as Informative by the WordPress Team. Today is the 45th day since I reported the vulnerability and yet the vulnerability is not patched as of writing this and I leave this for the reader to decide what they think of this and whether I should write more posts like this or not. Also, this vulnerability is in the default full site block editor that comes shipped with a default WordPress installation, so the scope of this vulnerability increases.
Update:- I reported a similar vulnerability to MSRC and they accepted it as a legit vulnerability and fixed it.
Table of Contents
- The Vendor
- CVE-2022-33994:- Stored XSS in WordPress via improper validation of SVG file loaded over an URL.
WordPress is the most popular Content Management System on this planet and runs more than 42% of all websites(that’s 810.6 million websites). It’s popularity and flexibility is what made it my choice for building my Blog. WordPress also comes with a lot options to make a site super secure, both at a code level and with plugins(which I don’t recommend). Now, it’s obvious that I’m biased towards WordPress and as such I don’t want to bore people by talking how great WordPress is.
Finding a vulnerability in WordPress was one of the goals in my list of goals and this vulnerability helped me shorten my list of goals by one line.:-) Now, the WordPress Team considers this vulnerability as just informative but MITRE thinks this is a real vulnerability and allocated me a CVE ID in less than 11 hours!
CVE-2022-33994:- Stored XSS in WordPress via improper validation of SVG file loaded over an URL.
WordPress is not a CNA partner of MITRE but as WordPress runs more than 42% of all websites on the planet, I decided to reported this vulnerability directly to them before reporting to MITRE. I looked for security.txt file on WordPress.org website and found their contact address is at a Bug Bounty Platform. So, I reported the vulnerability first there and this timeline starts from there. Today is the 45th day since I first reported the vulnerability to them and they’ve still not fixed this issue.
15/06/2022 – Reported the vulnerability to WordPress.
16/06/2022 – WordPress started investigating the vulnerability.
17/06/2022 – WordPress classified the vulnerability as informative and closed the report.
19/06/2022 13:45 – Reported the vulnerability to MITRE.
20/06/2022 00:19 – MITRE allocated me CVE-2022-33994.
So, the story starts from another project of mine. I found a similar vulnerability in another Vendor’s project which the Vendor acknowledged as a vulnerability and said they’re already aware of it but mentioned it as out of scope. So, basically the problem is WordPress doesn’t do any validation on image files that are being loaded over an URL. For e.g, if you try to upload a SVG file by using the WordPress image Upload button, it’ll give you an error saying :- Sorry, you are not allowed to upload this file type.
The same error shows up when you try the Media Library option. But as you can see from the image above, there is a third option called Insert from URL which allows to render remote files on a WordPress hosted site. But, the BIG problem is you can add an image file of any extension over an URL, i.e svg, php, xml, nuts, butts etc. and WordPress would allow it without showing any errors as above.
As you can see from the video above I was able to load the same SVG file that got rejected earlier. Now, lets talk about the more important part of this vulnerability, i.e why it can be considered serious.
<img src="https://malicious.domain/fox.svg" alt="" >
Also, even if the SVG backdoor didn’t execute in the context of the WordPress hosted domain, the XSS payload will get executed once the SVG file is opened directly(which a lot of people normally do, including me)! An attacker can implant a BeEF XSS hook or deploy other similar techniques and takeover the entire browser of the victim and not just the WordPress domain! This attack could further devolve into Remote Code execution if the victim’s browser is not updated and is vulnerable. Now, as this vulnerability requires user interaction this is not of very high severity but when you consider the fact that WordPress hosts 42% of all websites in the world this really becomes a high severity vulnerability and I think is one of the main reason MITRE allocated it a CVE in less the 12 hours! You’ll never know when one of your regular trusted blogs may be hosting such a backdoor.
But I know that still some mean minded folks would argue that this isn’t a vulnerability in WordPress as the XSS file loaded from another domain. If this is so, then tell me why the hell companies like Google and Slack went to the extent of validating files that are loaded over an URL and rejecting the files if they’re found to be SVG! Now similar to WordPress, Google and Slack also don’t allow uploading SVG files to their respective services but alongwith that they also don’t allow SVG files to load over an URL, which WordPress does! Here is a sample video showing how Google’s Blogger rejects SVG files:-
The interesting thing is Google doesn’t render SVG files even in their ubiquitous Google Photos app(try it yourself)! As you can see from the video above that Google Photos was also an option to insert an image but somehow the guys at Google figured out that someone can try to upload a SVG file through Google Photos and made sure nobody is able to do so. When I first learned this, I was like, WTF!? I’d like to give Google a big plus for that. Similarly, Slack also implements such a Security feature. But, this brings us to our more popular and more ubiquitous WordPress, which hadn’t thought that someday somebody will come up with such an idea. I’d say it is more of an oversight by WordPress Devs and they’ll fix this issue in future releases.
My first advice for anybody reading this is to use a browser extension that reports them when they visit a website that runs WordPress. This way you’ll be able to take precautions before opening any images in that website.
Next, my advice for WordPress website owners is to use the WordPress Classic Editor plugin in place of the default block editor/Gutenberg plugin. The Classic Editor plugin is not vulnerable to this. Note, this advice is a must for large websites that use role based approach to allow users to post content to their website and they must use another editor that doesn’t allow loading SVG files over an URL until an official fix is available .
Now, my advice for WordPress Team is to get rid of the “Insert from url” functionality as popular content creation websites like Facebook, LinkedIn, Medium etc. and image upload websites like Flickr, Unsplash etc. don’t allow loading images from an URL and only allow uploading images directly from the user’s device. If disabling the feature is not an option, then I’d recommend to implement a kind of XML/image parser(like Google and Slack) that validates the contents of remote images before rendering them.
Now, I’ve not tested this as the specifications are bit too much of reading and as I already have gotten the CVE I wanted, I’m not really keen on going through all of them. Also, even though a lot of websites and all of the above RFCs/Specifications make it look like that there could be a possibility of code execution, I’m still a bit skeptical about them and decided it’s not worth my time to explore this further. If someone finds a way to exploit this, then kindly share your payload and enlighten us.
Another CVE writeup down and three more CVEs to go. Out of the remaining three, two of them are similar to this vulnerability. This CVE was found through a black box pentesting approach and not through source code auditing, but still I think it’s a good vulnerability considering the popularity of WordPress. I really hope the WordPress devs will fix this vulnerability as soon as possible because after reading this some evil minded folks will start deploying XSS backdoors in websites, which may put a lot of people at risk, including me. Now, the WordPress Team wanted me to discuss this vulnerability publicly on Github and talk about possible solutions on fixing this, but instead I decided to publish it on my blog. As such, I think I’ve full permissions of WordPress in publishing this vulnerability. Thanks for reading. Peace!