CVE-2022-33994:- Stored XSS in WordPress

Introduction

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

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.

Timeline

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.

The Vulnerability

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.

SVG file upload not allowed

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.

WordPress has a lot of security features and one of them is that only someone with Editor and above privileges in WordPress can load arbitrary JavaScript/HTML code in a blog post. An user with the privileges of an Author or Contributor cannot load HTML tags like iframe, embed, script, svg etc. and these tags will get automatically removed if added by such a user. But the problem here is, the above vulnerability allows users with Author or below privileges to load SVG files with arbitrary Javascript code embedded in them. Now, the fun thing is when I submitted the vulnerability to MITRE, I mentioned in the vuln description that someone with Author/Contributor privileges can load arbitrary SVG files, but MITRE suggested me a changed description that someone with just Contributor privileges, which is the lowest privilege in WordPress, can load arbitrary HTML/JS code. I think MITRE were just trying to be helpful by suggesting the vulnerability is worse than I mentioned.:-)

Now, the question must be that the vulnerability looks all good, so why did WordPress classified this Vulnerability as Informative? Well, not all is good yet with this vulnerability. The problem now is browser protections will ignore the JavaScript embedded in SVG files if SVG images are added to the page as images, i.e within an <img tag.

<img src="https://malicious.domain/fox.svg" alt="" >

The SVG image will still render totally fine but the JavaScript inside it won’t load in the context of the WordPress hosted domain. Now, one would argue that they can embed an SVG file directly using the <svg> html tag or they can reference it using using an <iframe> or <object> tag which will effectively make it as if JavaScript is written outside the SVG file and is embedded directly into page. Yes, this would work but as we know an user with Author/Contributor privileges is not allowed to use the tags to embed HTML directly in WordPress, this method doesn’t works. So, I’d say that the argument of the WordPress Team was somewhat right even though the origin header of a GET request to the image shows the WordPress domain in logs.

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.

The Remediation

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.

Afterthought

Now, while trying to make the XSS payload load in context of the WordPress domain I came across SMIL. SMIL stands for Synchronized Multimedia Integration Language, which is an XML markup language that is supported by all latest browsers. Now from what I’ve read, a lot of websites and the latest SMIL specification itself suggest that even though browsers would prevent arbitrary JavaScript in SVG files from loading they’d allow SMIL code in SVG. SMIL helps in creating really nice SVG animations. For example look at this SVG image(Note, I’ve embedded this using WordPress Custom HTML option):-

Toy train SMIL SMIL animation of a little toy train demonstrating animateMotion along a path, by CMG Lee.

This is just a basic sample and is written entirely with SVG+SMIL code. Many developers have created some seriously cool SVG animations that are available on Github. Now, the problem is according to SMIL 3.0 specification we can use the JavaScript Document Object Model(DOM) in SMIL which in turn may allow us to create a XSS payload for SVG with native SMIL. Also, the security consideration for RFC 4536, which is the rfc for SMIL media content type, mentions that all of the security considerations for XML, as mentioned in RFC 3023, applies to SMIL. In short, every vulnerability that’s possible with XML files is possible with SVG+SMIL files!

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.

Conclusion

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!

Leave a Reply

Your email address will not be published. Required fields are marked *