Challenge 11: XSS CSP bypass through an inline script

Learn how a misconfigured CSP can be bypassed, potentially leading to the successful exploitation of cross-site scripting vulnerability.

Challenge 11: XSS CSP bypass through an inline script
XSS CSP Bypass

Welcome to learning XSS with the Kurukshetra Series.

Before getting started, ensure your Kurukshetra lab is up and running. Feel free to refer back to the below link.

Practical Hands-On Way to Learn XSS with Kurukshetra
Kurukshetra is an intentionally designed XSS-vulnerable application. XSS explained with examples and an open-source lab for practicing cross-site scripting vulnerability.

XSS Vulnerable App - By Design


‌XSS Challenge Walk-Through

Once your Kurukshetra XSS lab environment is up and running, Visit http://localhost:8066 and navigate to “XSS Challenge 11“.

XSS Challenge 11 page with payload
  1. Click and select the XSS Challenge 11 from the Kurukshetra app.
  2. Fill out our classic XSS payload in the given input field.
  3. Click on the “Submit” button.

Output:

XSS Payload Output

4. The application loads the page as usual and displays a text message, "Your XSS Payload" without any pop-ups.

5. Right-click and select “View page source“, then search for the injected XSS payload. The HTML response code will be displayed below.

XSS Payload Result's HTML Page Source

6. At the bottom of the HTML response, the payload was injected as provided and also aligned rightly with the HTML syntax. But our javascript didn't execute.

What might be happening in the background?

In the above screenshot, if the HTML output encoding is used, then the output must be displayed as “<” or “>” etc. Doesn’t look so. Also, if slash-escape is being used, then the prefix slashes must be displayed. Even that is not present.

Seems like our XSS payload is injected rightly but unable to execute. A possible guess is there is some sort of other XSS defense in place.

The web application might have enabled the Content Security Policy or other XSS protection headers. Let’s verify and understand what's happening in the background.

On the following XSS challenge page, Press the “F12” button on your keyboard and a new browser debugger window will be launched.

In browser debugger mode navigate to “Console” and observe the CSP violation messages will be displayed as shown below.

Observe Content-Security-Policy Errors

Web Browser clearly indicates some script code tried to execute but it's not compliant with the CSP policy set. Therefore it was blocked by the browser from executing.

In debugger mode, switch to "Network" and reload the challenge page.

Viewing Content-Security-Policy

Select the "ch11.php" page and observe on the right side in "Response Headers" the Content-Security-Policy header, which was set by the web application.

Understanding the CSP implementation

Breaking down the CSP policy defined by the web application

  1. script-src: specifies the sources from which scripts can be loaded.
  • https://facebook.com: allows scripts to be loaded from the domain facebook.com.
  • https://google.com: allows scripts to be loaded from the domain google.com.
  • unsafe-eval: This allows the eval() javascript function and the Function() constructor to execute dynamically created script code.
  • "data:": allows the execution of inline scripts (one which is directly embedded in the HTML) with data URIs.
  • "http://*": Wildcard "*" means allows scripts to be loaded from any HTTP sources (poses a security risk).

2. child-src: specifies the sources from which nested browsing contexts (such as iframes or embedded objects) can be loaded. In this case, 'none' specifies that no sources are allowed.

3. report-uri: specifies the URL where a browser should send violation reports if the policy is breached.

Overall, this CSP allows scripts to be loaded from trusted domains (facebook.com and google.com), as well as inline scripts and HTTP sources (which are generally not recommended due to security risks). It also allows the use of eval() and Function(), which can be used to exploit XSS attacks. Additionally, it prohibits the loading of nested browsing contexts and specifies a URL to which violation reports should be sent.

The above CSP policy clearly has some limitations and is not foolproof. That said, "data:" provided an entryway for us to try creating XSS inline scripts or load the XSS script code from any of the HTTP domains, tricking the application by loading from Google, etc.

Exploiting XSS using Inline scripts

(i.e., using data directive)

Let's go ahead and find a way to bypass the misconfigured CSP defenses. For the following demonstrations, we will be using the script-src's "data:" attribute to craft an XSS payload.

From the documentation script source "data:" can be used for inserting inline scripts directly into HTML documents.

The "data:" URI scheme allows data to be embedded directly in a URL or document, using a specific syntax that includes the "data:" prefix followed by the MIME type of the data, and the data itself.

Below is an XSS inline script using the "data:" URI scheme, which can be included directly, with the MIME type set to "text/javascript" and an "alert('xss')" data.

POC for XSS inline script

Above code will pop up with an "XSS" message when the javascript code is loaded and executed directly on the page.

Visit the "XSS challenge 11" page.

CSP-based XSS Payload Input

Enter the XSS inline script code in the input field and click on the "Submit" button.

Output:

XSS Alert Message

Immediately, we can see a pop-up message displayed on the web page. By this, we can confirm that we have successfully exploited the XSS vulnerability. :D

To further confirm, click on the "OK" message, then right-click and select "View page source". Search for the injected XSS inline script code.

HTML Page Source:

XSS Payload HTML Page Source

Observe this time, our injected script code is reflected back as given without any output being filtered.

The execution script code confirms we have successfully solved the XSS challenge 11. Yayy!!!.

Use of the "data:" URI scheme for inline scripts can be problematic from a security perspective, as it allows arbitrary code to be executed directly on the page, which is generally abused by attackers to perform cross-site scripting (XSS) attacks.


Summary

A Content Security Policy (CSP) policy restricts the types of content that can be loaded by a web page. When implemented correctly, a CSP can prevent cross-site scripting (XSS) attacks by limiting the sources from which scripts can be loaded.

However, if a CSP policy is misconfigured or contains errors, it can potentially allow XSS attacks to occur. For example, if a policy includes insecure sources, such as "unsafe-inline" or "data:", it can enable attackers to inject malicious scripts directly into a web page, potentially leading to XSS attacks.

Therefore, a well-configured CSP policy can block all XSS attacks, and it is important to ensure that CSP policies are correctly configured and free from insecure directives.