Content Security Policies (CSP) are an additional layer of security designed to detect and weaken certain types of attacks, including cross-site scripting (XSS) and data injection attacks. Whether it is data theft, website content contamination or the distribution of malicious software, these attacks are the main means.
The cause of
I found a surprise when I accidentally went to the Twitter page View Source.
<! DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Twitter</title> <style> body { background-color: #ffffff; font-family: sans-serif; } a { color: #1da1f2; } svg { color: #1da1f2; display: block; fill: currentcolor; height: 21px; margin: 13px auto; width: 24px; } </style> </head> <body> <noscript> <center>If you're not redirected soon, please <a href="/">use this link</a>.</center> </noscript> <script nonce="SG0bV9rOanQfzG0ccU8WQw=="> document.cookie = "app_shell_visited=1; path=/; max-age=5"; location.replace(location.href.split("#")[0]); </script> </body> </html>Copy the code
Compared to the usual see other site source, can be said to be very refreshing. No cluttered labels, but just as many features. It’s very confusing to think that this is all the Source code for the page, but it’s easy to see that this isn’t the actual HTML code by looking in the Source panel of DevTools. But why the page source code is given such a clean version, not here.
When you look at the script tag, you notice an unrecognized nonce attribute. It and its cryptic string succeeded in piquing my curiosity. Go to see the source of Google home page, there are also a number of nonce use. It’s time to learn what a nonce is here.
! <script nonce="SG0bV9rOanQfzG0ccU8WQw=="> document.cookie = "app_shell_visited=1; path=/; max-age=5"; location.replace(location.href.split("#")[0]); </script>Copy the code
Content Security Policy (CSP)
To understand nonce, learn about Content-Security-Policy(CSP).
We all know that browsers have the same origin policy security restrictions, that is, each site is only allowed to load data from its own origin, https://a.com cannot load resources from https://b.com. Each site is tightly confined to its own island, its own sandbox, so it is safe to keep the whole network from getting messy. Mainly, it solves most security problems. Without the same-origin policy, malicious code could easily execute on the browser side and get all kinds of private information: bank accounts, social data, etc.
How to share data between the sites, of course, there is a way to understand CORS.
In practice, the problem is that same-origin scripting is not foolproof. Cross-domain attack Cross-Site Scripting (XSS) contains a variety of ways to circumvent restrictions, in the form of information theft or attack by injecting malicious code into a page. For ugC-type sites, for example, because the content is user-created, this opens up a large window for user-typed content to run on the page. Of course, since we all know there will be injection attacks, anti-XSS filtering of user input is standard.
Content-security-policy, on the other hand, adds a layer of protection to the browser and can greatly reduce such attacks.
The principle of
The CSP tells the browser a set of rules that strictly dictate which resources are allowed on a page from which sources, and rejects anything that isn’t specified. Compared to the same origin policy, CSP can be said to be very strict.
There are two ways to implement it:
- Adding a server
Content-Security-Policy
The response header specifies the rule - HTML to add a tag to specify
Content-Security-Policy
The rules
CSP rules in the Mobile.twitter.com header
For testing convenience, the following examples use the
tag to enable CSP rules. However, there are some directives in
that cannot be used, as you’ll see later. Only in the response header can the full limit instruction be used.
A simple example
Create an HTML file to put in the following:
csp_test.html
<! DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Security-Policy" content="script-src 'self' https://unpkg.com"> <title>CSP Test</title> </head> <body> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> </body> </html>Copy the code
Open a local server in the directory where the test file is located to access it, using Python’s own server:
python -m SimpleHTTPServer 8000
Copy the code
Then visit localhost:8000 to see the result:
Access when CSP rules are met
Then we change the Content-security-policy to not allow any resources and try again:
csp_test.html
<! DOCTYPE html> <html lang="en"> <head> - <meta http-equiv="Content-Security-Policy" content="script-src 'self' https://unpkg.com"> + <meta http-equiv=" content-security-policy "Content ="script-src 'none' "> <title>CSP Test</title> </head> <body> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> </body> </html>Copy the code
CSP rule resources are blocked
Let’s explain the CSP rules set here and understand why resource loading fails.
CSP rules, whether specified in headers or
tags, have a uniform format of values, consisting of a series of CSP directives.
Example:
Content-Security-Policy: <policy-directive>; < policy directive - >...Copy the code
The directive is specified in the CSP specification to specify the source of a resource. For example, in the previous example, script-src specifies which legitimate sources a script can come from, and img-src specifies an image.
base-uri
Restrictions may appear on the page<base>
Links in the tag.child-src
Lists links available for workers and embedded as frames. Such as:child-src https://youtube.com
Indicates that video resources can only be embedded from Youtube.connect-src
Address that can initiate a connection (via XHR, WebSockets, or EventSource).font-src
Font source. For example, to use Google Web Fonts you need to addfont-src https://themes.googleusercontent.com
The rules.form-action
<form>
The address to which the label can be submitted.frame-ancestors
Which sources the current page can be embedded from (andchild-src
Quite the opposite). Acting on the<frame>
.<iframe>
.<embed>
及<applet>
. The instruction cannot be passed<meta>
Specifies and only applies to resources that are not HTML document types.frame-src
This directive was deprecated in Level 2 but will be restored in Level 3. Falls back to an unspecified conditiontochild-src
The instructions.img-src
Specify the image source.media-src
Limit the source of audio and video resources.object-src
Source of Flash and other plug-ins.plugin-types
Restrict the types of plug-ins that can be loaded on a page.report-uri
Specify an address to receive a CSP report, and the browser will send the report if the corresponding command fails. Can’t pass<meta>
Tag to specify.style-src
Restrict the source of the style file.upgrade-insecure-requests
Rewrite the page address from HTTP to HTTPS on the client. Used when the site has a large number of old addresses that need to be redirected.worker-src
Directives in CSP Level 3 that specify addresses that can be used in worker, shared worker, or service worker.
Child-src looks similar to frame-rooted. The former specifies which iframes can be loaded in the page, while the latter specifies who can load the page with iframes. For example, two web pages A and B from different sites, B has iframe loaded with A. then
- The frame-rooted of A needs to contain B
- The child-src of B needs to contain A
By default, these directives are Max conditional open, which can be interpreted as a default value of *. For example, img-src, if not explicitly specified, can load image resources from anywhere.
There is also a special directive, default-src, which, if specified, changes the default values of these unspecified directives. If img-src is not specified, the default value of img-src is *, which can load images from all sources. When default-src is set, the default value is default-src.
A common practice is to set default-src ‘self’ so that all resources are confined to the same domain as the page. If you want to load the image from the CDN, add the image source separately.
The Content ws-security - Policy: the default - SRC 'self'; img-src https://cdn.example.comCopy the code
Now look at the example at the beginning, maybe it makes sense now. The React library needs to be loaded from the CDN, so our
tag specifies the following CSP rules:
script-src 'self' https://unpkg.com
Copy the code
Self and later none are default values and must be enclosed in quotation marks, otherwise they will be parsed as urIs. The CSP rule here states that scripts on a page can only be loaded from the same domain and https://unpkg.com. If we remove the latter, the React library will also fail to load as shown in the screenshot above, and the console will have a log of the failed load and the triggered rules listed.
Changing to None means that no scripts are loaded on the page, even those on your own site. Here try creating a script file named test.js next to csp_test.html:
test.js
Alert (' Greetings from test.js! ')Copy the code
Also reference it in the page:
csp_test.html
<! DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Security-Policy" content="script-src 'none'"> <title>CSP Test</title> </head> <body> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> + <script src="./test.js"></script> </body> </html>Copy the code
Page execution result:
Script-src None will not load any scripts on the page
Yes, even your own scripts cannot be loaded and executed. The CSP is so strict and clear that there is no ambiguity. So when specifying the source, we need to verify that the URI is correct.
The acceptable value of the instruction
There are two ways to write the source of instructions that follow
- The preset value
- URI wildcard
The preset value
The default values are:
- None doesn’t match anything.
- Self matches the current field, but not the subfields. For example, example.com does, but api.example.com fails.
- Unsafe-inline allows for inline scripts and styles. Yes, that’s right, there are rules for what’s embedded in a page.
- Unsafe-eval allows execution of scripts created dynamically from strings, such as eval, setTimeout, and so on.
In particular, inline scripts and styles on pages are subject to strict CSP control and cannot be executed by browsers unless explicitly specified.
Consider the following code:
csp_test.html
<! DOCTYPE html> <html lang="en"> <head> <title>CSP Test</title> <style> body{ color:red; } </style> </head> <body> <h1>Hello, World! </h1> <script> window.onload=function(){ alert('hi jack! ') } </script> </body> </html>Copy the code
Case where no CSP is specified
According to the MDN description, if the site does not specify CSP none, the browser does not turn on the corresponding check by default, so everything above works fine, subject only to normal co-domain restrictions.
If the site doesn’t offer the CSP header, Browsers likewise use the standard SAME-origin policy. – From MDN description about Content Security Policy (CSP)
We add the CSP restriction:
csp_test.html
<! DOCTYPE html> <html lang="en"> <head> + <meta http-equiv="Content-Security-Policy" content="default-src 'self'"> <title>CSP Test</title> <style> body{ color:red; } </style> </head> <body> <h1>Hello, World! </h1> <script> window.onload=function(){ alert('hi jack! ') } </script> </body> </html>Copy the code
By default, configuration sites only show resources in the same domain, but note that this setting does not include inlining, so the result is shown below.
Inline codes are disabled
How to fix it. If we want to allow inline scripts or styles within the page, we need to specify this explicitly with script-src and style-src.
csp_test.html
<! DOCTYPE html> <html lang="en"> <head> ! <meta http-equiv=" content-security-policy "Content ="default-src 'self' 'unsave-inline' "> <title>CSP Test</title> <style> body{ color:red; } </style> </head> <body> <h1>Hello, World! </h1> <script> window.onload=function(){ alert('hi jack! ') } </script> </body> </html>Copy the code
The default trusted sources for the default-src ‘self’ ‘unsave-inline’ configuration are those that are in the same domain as the page, and those that are inline.
Refresh the page, and the styles and scripts can execute normally again.
Safe-inline is generally not recommended (nor is safe-eval), as inline scripts and styles are inconvenient to maintain and do not take advantage of well-organized code. The best practice is to separate styles into style files, load scripts in separate JS files, and keep the HTML files pure. Even onclick= “myHandler” or href= “javascript:;” This usually common writing method, also belongs to the inline script, is in need of transformation.
If the page doesn’t have to be inline, there’s another way. These inline script or style tags in the page assign an encryption string, which is generated by the server and added to the page’s response header.
< script nonce = EDNnf03nceIOfn39fn3e9h3sdfa > / / here placed inline code in the HTML < / script >Copy the code
The content-security-Policy configuration of the page HTTP response header contains the same encrypted string:
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
Copy the code
Notice the nonce- prefix here.
That’s the way you see it at the beginning of the article, but you get it.
The
The encrypted string must be random and unpredictable, otherwise it will not be secure and will be regenerated every time the page is accessed.
In addition to using NOCE to specify encrypted strings, you can do this by obfuscating hash values. Instead of adding nonce to the tag, the embedded code itself is hash generated by an encryption algorithm, which supports SHA256, SHA384 and SHA512, and then used as a value in the CSP instruction. In this case, the prefix used in CSP is the corresponding algorithm name.
An example of hash:
<script>alert('Hello, world.'); </script>Copy the code
Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='
Copy the code
eval
There are places in JS where you can create code dynamically and execute it as a string. This is considered unsafe and is therefore not recommended, as it is in general best practice.
- SetTimeout /setInterval accepts a string to be executed as code. SetTimout (” alert (1), 1000).
- The eval. The eval (‘ alert (1) ‘).
- Function constructor. New Function (‘ alert (1) “).
As with inline, there is a special directive unsafe-eval to allow execution of similar code. However, it is recommended that the eval and Function constructors not be used, and that setTimeout/setInterval be modified to a non-string form.
setTimout(function(){ alert(1); }, 1000).Copy the code
URI
In addition to the default values above, it can be matched by providing a full URI or an address with a wildcard * to specify the legitimate source of the resource. The rules for the URI are the Same as for configuring the server’s cross-domain response header, see same-Origin Policy.
*://*.example.com:*
Will match all of themexample.com
Subdomain, but not includedexample.com
.http://example.com
和http://www.example.com
Are two different URIs.http://example.com:80
和http://example.com
There are also two different URIs, although the default port on the site is 80
A complete URI consists of the following parts: URI = Scheme :[//authority]path[? Query][#fragment]
Authority = [userinfo@]host[:port]
So you can think of one of these terms as different, and those are both urIs. It is important to understand that, as in the first example *.example.com listed above, it is easy to assume that since all subdomains of the domain are allowed, example.com must also be legal.
Because URIs are dynamically matched, this explains why the default values mentioned above are quoted. Because if not quoted, self would indicate that host is self’s resource address, not the original meaning.
The configuration of priority CSPS is flexible. Each instruction can specify multiple sources, separated by Spaces. A CSP rule can be composed of multiple instructions separated by a semicolon. There is no order between the instructions because each one is doing its job. Even within a single response, the Content-security-policy response header can be set repeatedly.
Let’s look at how CSPS behave in these situations.
- For multiple response headers, the strictest rules take effect. For example, in the following two response headers, although set in the second
connect-src
allowhttp://example.com/
But it’s set in the first oneconnect-src
为none
So more strictnone
Will take effect. seeMultiple content security policies.
Content-Security-Policy: default-src 'self' http://example.com;
connect-src 'none';
Content-Security-Policy: connect-src http://example.com/;
script-src http://example.com/
Copy the code
- If the same command is specified more than once, the first one will take precedence and subsequent ones will be ignored.
csp_test.html
<! DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Security-Policy" content="default-src 'self'; default-src 'unsafe-inline';" > <title>CSP Test</title> <style> body{ color:red; } </style> </head> <body> <h1>Hello, World! </h1> <script> window.onload=function(){ alert('hi jack! ') } </script> </body> </html>Copy the code
Effect display when configuring the same instruction repeatedly
Intelligently, the browser will not only print resources and instructions that cannot be detected, but will also indicate instructions that have been ignored during repeated configuration.
- The specified
default-src
In case it will act asFetch
The default value for the class directive. namelydefault-src
Does not apply to all directives. The default value for other directives remains*
.
Send the report
When an illegal resource is detected, in addition to the error message seen by the console, the browser can also send the log to the server for subsequent analysis. The address to receive the report can be configured using the report-URI directive in the Content-Security-Policy response header. Of course, the server needs to write the corresponding service to receive this data.
Content-Security-Policy: default-src 'self'; . ; report-uri /my_amazing_csp_report_parser;Copy the code
The server gets the data in JSON form.
{
"csp-report": {
"document-uri": "http://example.org/page.html",
"referrer": "http://evil.example.com/",
"blocked-uri": "http://evil.example.com/evil.js",
"violated-directive": "script-src 'self' https://apis.google.com",
"original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
}
}
Copy the code
The report model
CSP provides a reporting mode in which resources are not really loaded restrictively, but only reported on detected problems, sent as JSON data to the location specified by the report-URI.
By specifying content-security-policy-report-only instead of content-security-policy, the reporting mode is enabled.
Content-Security-Policy-Report-Only: default-src 'self'; . ; report-uri /my_amazing_csp_report_parser;Copy the code
Of course, you can specify both headers at the same time, and the rules in each will execute normally without affecting each other. Such as:
Content-Security-Policy: img-src *; The Content ws-security - Policy - Report - Only: img SRC "none"; report-uri http://reportcollector.example.com/collector.cgiCopy the code
Here the image will still load normally, but img-src ‘None’ will also detect it and send a report.
The report mode is very useful for testing. Before starting CSP, it is definitely necessary to do a comprehensive test of the whole station, and fix the problems found in time before really starting, such as the transformation of the inline code mentioned above.
Recommended practices
Such security measures are of course implemented as soon as possible. Here’s how to do it:
- First, only open the report mode, see the scope of impact, modify the problem.
- Add instructions from
Default - SRC 'none'
Start, check the error, and gradually add rules until the requirements are met. - After it goes online, observe it for a period of time, and then switch from the reporting mode to the enforcement mode.
Browser compatibility
At present, most of the Level 3 specification released has not been implemented by browsers. According to the data of Can I Use, the functions of Level 2 have been well supported except IE. Here’s one more stat from the W3C tracking browser Implementation: Implementation Report for Content Security Policy Level 2.
In cases where browsers do not support it, there is no need to worry about falling back on the same-origin policy limits.
reference
Original: www.cnblogs.com/Wayou/p/int… Author: Liu Waayong