Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

内容安全策略CSP是什么? #244

Open
FrankKai opened this issue Dec 26, 2020 · 0 comments
Open

内容安全策略CSP是什么? #244

FrankKai opened this issue Dec 26, 2020 · 0 comments

Comments

@FrankKai
Copy link
Owner

FrankKai commented Dec 26, 2020

当我们谈起如何防范web安全中的XSS攻击时,通常会说:浏览器引入了内容安全策略,也就是CSP(Content Security Policy),去解决XSS攻击的问题。

有人说,CSP的核心思想是让服务器决定浏览器能够加载哪些资源,相当于一个前端资源白名单。这样做的目的是抵御XSS攻击,提升前端安全性。

那么CSP到底什么呢?
这句对CSP的概括是否准确呢?

  • CSP前言
  • 面临的威胁
  • 如何使用CSP
  • 示例:常用的使用示例
  • 测试你的策略
  • 开启报告
  • 违规报告语法
  • 违规报告采样
  • CSP指令指南
  • 腾讯AlloyTeam两篇非常好的CSP文章

CSP前言

Content Security Policy(CSP)是一个检测和减轻确定类型攻击的内容安全层,这些确定攻击类型包括XSS(Cross Site Scripting)攻击和数据注入攻击。这些攻击可以造成网站的数据盗窃,网站污损和恶意软件安装。

CSP是完全的向后兼容的(除了CSP2.0版本有一些明显的在兼容性上的问题;更多细节可以看1.1章节)。
服务器实现了CSP而浏览器不支持的,浏览器可以正常工作,但是浏览器会忽略CSP,默认使用标准的web同源策略。如果网站没有提供CSP头,浏览器同样会使用标准的同源策略。

为了开启CSP,你需要配置的web服务器(Apache, Nginx) 去返回Content-Security-Policy HTTP头。(有时你可能会看到X-Content-Security-Policy头,但是这是一个老版本的头,无需关心)

或者,可以使用<meta>标签去配置策略,例如<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*;child-src 'none'; ">

面临的威胁

缓解XSS攻击

设计CSP的一个重要原因就是缓解和报告XSS攻击。XSS利用浏览器对服务器接收的内容的信任发起攻击。因为浏览器信任内容源,所以恶意脚本在受害者的浏览执行,即使内容并不是来自于它应该来自的地方。

CSP通过指定浏览器的源,可以使得服务器管理者减少或者消除XSS发起的攻击。一个CSP兼容的浏览器会只接收在白名单域名下的资源文件,忽略其他脚本(内联脚本或者事件处理html属性)

还有一个最终的保护形式,全局禁止脚本执行可以使得站点上的所有脚本不执行。

缓解数据包嗅探攻击

除了限制哪些源可以加载内容以外,服务器还可以指定哪个协议和端口被使用;例如(来自一个理想的标准端口),一个服务器可以指定所有内容都通过HTTPS加载。一个完整的数据传输安全策略不仅仅包含HTTPS传输数据,也包括通过设置cookie的secure属性并且自动重定向到HTTP页面到HTTPS页面。网站可以使用strict-Transport-SecurityHTTP头去确保只通过加密通过去连接浏览器和服务器。

如何使用CSP

配置内容安全策略主要是通过给网页增加Content-Security-PolicyHTTP头,设置这个头的值可以控制用户端可以加载哪些资源。例如, 一个上传和展示图片的页面,需要允许任何地方的图片都可以展示,但是提交表单的时候需要限制到指定端口。 一个适当设计的内容安全策略可以阻止网站受到XSS攻击。这个文章将解释如何设置内容安全头。

指定你的策略

你可以使用Content-Security-PolicyHTTP头去设置策略,例如:

Content-Security-Policy: policy

policy是一个字符串,用于描述你的内容安全策略。

写一个策略

使用一系列策略指令来描述策略,每个策略指令都描述特定资源类型或策略区域的策略。您的策略应包括default-src策略指令,这是其他资源类型没有自己的策略时的后备(有关完整列表,请参阅default-src指令的说明)。策略需要包括default-src或script-src指令,以防止运行内联脚本以及阻止使用eval()。策略需要包括default-src或style-src指令,以限制从<style>元素或样式属性应用内联样式。有针对各种项目类型的特定指令,因此每种类型都可以有自己的策略,包括字体,框架,图像,音频和视频媒体,脚本和工作程序。

示例:常用的使用示例

网站管理员想要所有的内容都来自自己的origin(排除子域)

Content-Security-Policy: default-src 'self'

网站管理员想要所有的内容来自一个可信域及其子域

Content-Security-Policy: default-src 'self' *.trusted.com

网站管理员想要允许web应用的用户在自己的内容中可以包含任意源的图片,但是限制音频,视频为指定的提供者,所有的脚本文件只能来源于部署了文件的机器

Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com

这里,默认内容只允许来自于当前文档源:

  • 图片来自任意位置,*号通配符
  • 媒体资源可以来源于media1.com和media2.com,不能来源于它们的子网站
  • 可执行脚本只能来源于userscripts.example.com

一家在线银行的网站管理员想要确保所有的内容都是使用TLS加载的,为了抵御请求窃听

Content-Security-Policy: default-src https://onlinebanking.jumbobank.com

一家在线商店的网站管理员想要在电子邮件中允许HTML,图片可以来自于任意源,但是禁止js或者其他有危险的内容

Content-Security-Policy: default-src 'self' *.mailsite.com; img-src *

注意script-src没有被特殊声明,这是因为在CSP这个例子中,已经设定了default-src 'self',这也就意味着这个网站加载的脚本只能来源于自己的服务器

测试你的策略

为了便于部署,CSP可以使用只读模式部署。策略不是强制的,但是任意违规都会报告给提供的URL。另外,仅报告只读头可以用于测试策略的未来修订版,而不用实际部署它。
可以使用Content-Security-Policy-Report-OnlyHTTP头去设置策略:

Content-Security-Policy-Report-Only: policy

如果Content-Security-Policy-Report-Only头和Content-Security-Policy头在同一个响应中返回,两种策略都生效。Content-Security-Policy标头中指定的策略被强制执行,而Content-Security-Policy-Report-Only策略仅生成报告,但不强制执行。

开启报告

默认情况下,违规报告不会被发送。为了开启违规报告,你需要声明report-uri策略指令,提供一个URI去接收传送报告:

Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi

当你需要设置服务器去接收报告的时候,服务器可以按照您认为合适的任何方式存储或者处理它们。

违规报告语法

违规报告JSON对象包含以下数据:

  • blocked-uri
    通过内容安全策略加载时被阻止的资源URI。如果被阻塞的URI来自一个不同的源而不是document-uri的时候,被阻塞的URI被截断为协议,主机和端口。
  • disposition
    无论是"enforce"或者"report",都依赖于Content-Security-Policy-Report-Only或者Content-Security-Policy头。
  • document-uri
    违规发生地方的文档url
  • effective-directive
    强制执行导致违规的指令。
  • original-policy
    Content-Security-Policy HTTP头设置的原始策略。
  • referrer
    发生违规的文档的referrer。
  • script-sample
    行内脚本,事件处理器,或者样式的前40行
  • status-code
    实例化全局对象资源的http状态码
  • violated-directive
    违反的策略部分的名称

违规报告采样

http://example.com/signup.html仅支持从cdn.example.com下载样式表

Content-Security-Policy: default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports
<!DOCTYPE html>
<html>
  <head>
    <title>Sign Up</title>
    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    ... Content ...
  </body>
</html>
{
  "csp-report": {
    "document-uri": "http://example.com/signup.html",
    "referrer": "",
    "blocked-uri": "http://example.com/css/style.css",
    "violated-directive": "style-src cdn.example.com",
    "original-policy": "default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports"
  }
}

CSP指令指南

Content Security Policy请求头由一个或者多个指令组成,多个指令的话由冒号”;“分隔

default-src

default-src指令定义了加载资源(js,图片,css,字体,ajax请求,frame,h5资源)的默认策略。
不是所有指令都回退到default-src

default-src 'self' cdn.example.com;

script-src

定义js资源的有效路径。

script-src 'self' js.example.com;

style-src

定义css资源的有效路径。

style-src 'self' css.example.com;

img-src

定义图片资源的有效路径。

img-src 'self' img.example.com;

connect-src

应用与XMLHttpRequest(AJAX),WebSocket,fetch(),<a ping>或EventSource。如果不允许会返回一个400状态码。

connect-src 'self';

font-src

定义字体的有效路径(通过@font-face加载)

font-src font.example.com;

object-src

定义插件的资源,例如<object><embed><applet>

object-src 'self';

media-src

定义音频和视频的有效资源,例如HTML5的<audio><video>

media-src media.example.com;

frame-src

定义可加载frame的资源。在CSP2.0中,不推荐frame-src,推荐child-src。CSP3.0也推荐使用child-src。

frame-src 'self';

sandbox

类似于frame sandbox属性。

sandbox allow-forms allow-scripts;

report-uri

CSP失败情况下报告的URI。CSP3.0推荐使用report-to指令。

report-uri /some-report-uri;

child-src

定义web worker和嵌入的浏览器上下文(例如frame,iframe)的资源

child-src 'self'

form-action

定义了HTML<form>action的有效资源

form-action 'self'

frame-ancestors

<frame> <iframe> <object> <embed> <applet>嵌入的资源。如果将这个设置为'none',等价于X-Frame-Options: DENY

frame-ancestors 'none';

plugin-types

定义插件的MIME type。

plugin-types application/pdf

base-uri

定义HTML的src白名单。

base-uri 'self';

report-to

report-to groupName;

worker-src

限制Worker,SharedWorker,ServiceWorker的URL。

worker-src 'none';

manifest-src

manifest-src 'none';

prefetch-src

prefetch和prerender的请求

prefetch-src 'none'

navigate-to

navigate-to example.com

腾讯AlloyTeam两篇非常好的CSP文章

XSS终结者-CSP理论与实践
《Csp Nonce – 守护你的 inline Script》

参考文章:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
https://content-security-policy.com/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant