Reflected XSS protected by CSP, with CSP bypass

Description

This lab uses CSP and contains a reflected XSS vulnerability.

To solve the lab, perform a cross-site scripting attack that bypasses the CSP and calls the alert function.

Please note that the intended solution to this lab is only possible in Chrome.

Approach

After accessing the lab, I used the search functionality while proxying the requests through Burp Suite with the FoxyProxy extension. I noticed something special in the response's Content Security Policy (CSP) header:

HTTP/2 200 OK
Content-Type: text/html; charset=utf-8
Content-Security-Policy: default-src 'self'; object-src 'none';script-src 'self'; style-src 'self'; report-uri /csp-report?token=

I observed that the report-uri directive includes a token parameter. To test this, I added the token parameter with a random string and checked the response:

GET /?search=qwe&token=ichyaboy HTTP/2
Host: 0a39008e04c8fd2d83ea82120002002a.web-security-academy.net
Cookie: session=yVtz5dX44USPkW4xVjcJBtutYJEoosZz
...

The response showed my input reflected in the actual CSP header:

Since I could write to the CSP header, my goal was to overwrite the script-src 'self' directive to allow script execution. After reading an article on Bypassing CSP with Policy Injection, I discovered that I could use the script-src-elem directive. This directive allows control over script blocks and permits event handlers while blocking script elements. This means using <script>alert(1)</script> would not work, but using JavaScript inside an event handler, such as <a href="#" onclick="alert(1)">ichyaboy</a>, would work.

I crafted a payload to inject into the search parameter and added a CSP injection payload in the token parameter:

URL-decoded, the payload looks like this:

This payload blocks script tags but allows event handlers. By adding this URL-encoded payload to the URL:

I saw a link labeled ichyaboy. When clicked, the alert box popped up, indicating the lab was solved.

Alternatively, I could set the policy to allow inline scripts like <script>alert('inline script')</script> by setting script-src-elem to 'unsafe-inline'. The full payload would look like this:

Adding this payload to the URL:

When accessing that link, the alert box popped up, confirming that the lab was solved. I solved the lab in two different ways to better understand CSP injection.