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 scriptingarrow-up-right 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 Injectionarrow-up-right, 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.