威胁
跨站脚本攻击(Cross-site scripting)
- 跨站脚本攻击Cross-site scripting (XSS)是一种安全漏洞,攻击者可以利用这种漏洞在网站上注入恶意的客户端代码。
- 攻击者可以突破网站的访问权限,冒充受害者
- 以下2种情况下,容易发生XSS攻击:
- 从一个不可靠的链接进入到一个web应用程序。
- 没有过滤掉恶意代码的动态内容被发送给web用户。(可以上传动态内容得接口没有过滤恶意代码)
- 恶意内容一般包括 JavaScript,但是,有时候也会包括HTML,FLASH。
XSS攻击可以分为3类:存储型(持久型)、反射型(非持久型)、基于DOM。
存储型XSS
- 注入型脚本永久存储在目标服务器上。当浏览器请求数据时,脚本从服务器上传回并执行。(当前网站支持上传数据,但是对数据得内容没有进行过滤。)
- 例如:上传一个图片,但是图片得实际路径指向一个脚本的url,由于脚本url在未设置CSP时支持跨域,当该图片被其他用户加载时就加载运行了该脚本。当前网站的个人信息就会被该脚本以合法的方式获取
反射型XSS(非持久性XSS)
- 当用户点击一个恶意链接,或者提交一个表单,或者进入一个恶意网站时,注入脚本进入被攻击者的网站
- Web服务器将注入脚本,比如一个错误信息,搜索结果等 返回到用户的浏览器上。
- 这种方式是利用某些特别的接口,这些接口返回的数据和提交的内容相关,但又未对提交的内容进行过滤。导致服务器返回的内容把恶意代码注入到了客户端浏览器中。
- 例如:在旧版的浏览器中,input的值会写入value属性中
<input value='默认值可以修改' type='text'></input>
,如果某个返回的数据如下就会向客户端浏览器注入恶意代码
返回value值为 '/><script>...dosome...</script><input value='
这时渲染的input标签会变为 <input value=''/><script>...dosome...</script><input value='' type='text'></input>
JS代码就会被注入执行了
基于DOM的XSS(本地利用漏洞,这种漏洞存在于页面中客户端脚本自身。)
- 浏览器自身有安全漏洞,用户访问了恶意网站,这些具有针对这些漏洞进行攻击的脚本就会利用这些漏洞绕过浏览器安全机制获取信息
- 这种攻击危害较小,只针对浏览器版本没有及时更新且访问了恶意网站的用户
—————————————————
数据包嗅探攻击
- 除限制可以加载内容的域,服务器还可指明哪种协议允许使用;比如 (从理想化的安全角度来说),服务器可指定所有内容必须通过HTTPS加载。
- 一个完整的数据安全
- 传输策略强制使用HTTPS进行数据传输
- 所有的cookie标记安全标识
- 提供自动的重定向使得HTTP页面导向HTTPS版本。
- 网站也可以使用 Strict-Transport-Security HTTP头部确保连接它的浏览器只使用加密通道。
———————————————————————————————————————
使用 CSP
- 内容安全策略 (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。
- CSP2 在向后兼容有明确提及的不一致
- 为使CSP可用, 你需要配置你的网络服务器返回 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';">
- Content-Security-Policy 某些指令源需要配合标签属性使用,例如:nonce
- CSP通过指定有效域——即浏览器认可的可执行脚本的有效来源——使服务器管理者有能力减少或消除XSS攻击所依赖的载体。
- 一个CSP兼容的浏览器将会仅执行从白名单域获取到的脚本文件,忽略所有的其他脚本 (包括内联脚本和HTML的事件处理属性)。
制定策略
- policy参数是一个包含了各种描述你的CSP策略指令的字符串。
Content-Security-Policy: policy
描述策略
- 一个策略由一系列策略指令所组成,每个策略指令都描述了一个针对某个特定类型资源以及生效范围的策略。
- 你的策略应当包含一个default-src策略指令,在其他资源类型没有符合自己的策略时应用该策略
- 一个策略可以包含 default-src 或者 script-src 指令来防止内联脚本运行, 并杜绝eval()的使用。
- 一个策略也可包含一个 default-src 或 style-src 指令去限制来自一个 <style> 元素或者style属性的內联样式。
对策略进行测试
- 为降低部署成本,CSP可以部署为报告(report-only)模式
- 在此模式下,CSP策略不是强制性的,但是任何违规行为将会报告给一个指定的URI地址。
- 一个报告模式的头部可以用来测试一个修订后的未来将应用的策略而不用实际部署它。
- 用Content-Security-Policy-Report-Only HTTP 头部来指定你的策略
- 如果Content-Security-Policy-Report-Only 头部和 Content-Security-Policy 同时出现在一个响应中,两个策略均有效
- 在Content-Security-Policy 头部中指定的策略有强制性 ,而Content-Security-Policy-Report-Only中的策略仅产生报告而不具有强制性
- 支持CSP的浏览器将始终对于每个企图违反你所建立的策略都发送违规报告,如果策略里包含一个有效的report-uri 指令
Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi
- Don't implement the above policy yet; instead just report violations that would have occurred(尚未实施上述策略;只需报告可能发生的违规行为。)
Content-Security-Policy-Report-Only: default-src https:; report-uri /csp-violation-report-endpoint/
违例报告的语法
- 作为报告的JSON对象报告包含了以下数据:
- document-uri 发生违规的文档的URI。
- referrer 违规发生处的文档引用(地址)。
- blocked-uri 被CSP阻止的资源URI。如果被阻止的URI来自不同的源而非文档URI,那么被阻止的资源URI会被删减,仅保留协议,主机和端口号。为了防止泄露跨域资源的敏感信息
- violated-directive 违反的策略名称。
- original-policy 在 Content-Security-Policy HTTP 头部中指明的原始策略。
违例报告样本
{
"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"
}
}
——————————————————————————————————————————
Content-Security-Policy
语法
Content-Security-Policy: <policy-directive>; <policy-directive>
指令
获取指令
- 通过获取指令来控制某些可能被加载的确切的资源类型的位置。
- child-src 为网络工作者(Service Worker和其他内嵌浏览器内容(例如用<frame>和<iframe>加载到页面的内容)定义合法的源地址。
- frame-src 设置允许通过类似<frame>和<iframe>标签加载的内嵌内容的源地址。
- worker-src 限制Worker、SharedWorker或者ServiceWorker脚本源。
- connect-src 限制能通过脚本接口加载的URL。
- default-src 为其他取指令提供备用服务(child-src、connect-src、font-src、frame-src、img-src、manifest-src、media-src、object-src、script-src、style-src、worker-src)
- font-src 设置允许通过@font-face加载的字体源地址。
- img-src 限制图片和图标的源地址
- manifest-src 限制应用声明文件(manifest)的源地址。
- media-src 制通过<audio>、<video>或<track>标签加载的媒体文件的源地址。
- <track> 元素 被当作媒体元素—<audio> 和 <video>的子元素来使用。它允许指定计时字幕(或者基于时间的数据),例如自动处理字幕。
- object-src 限制<object>、<embed>、<applet>标签的源地址。(这3个标签再HTML5中已经废弃)
- prefetch-src 指定预加载或预渲染的允许源地址。?
- script-src 限制JavaScript的源地址。
- style-src 限制层叠样式表文件源。
- webrtc-src 指定WebRTC连接的合法源地址。(实验)
- WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。
文档指令
- 文档指令管理文档属性或者worker环境应用的策略。
- base-uri 限制在DOM中<base>元素可以使用的URL。
- plugin-types 通过限制可以加载的资源类型来限制哪些插件可以被嵌入到文档中。?
- sandbox 类似<iframe> sandbox属性,为请求的资源启用沙盒。
- sandbox 对呈现在iframe框架中的内容启用一些额外的限制条件。
导航指令
- 导航指令管理用户能打开的链接或者表单可提交的链接
- form-action 限制能被用来作为给定上下文的表单提交的 目标 URL (说白了,就是限制 form 的 action 属性的链接地址)
- frame-ancestors 指定可能嵌入页面的有效父项<frame>, <iframe>, <object>, <embed>, or <applet>.
- navigation-to 限制文档可以通过以下任何方式访问URL (a, form, window.location, window.open, etc.?)(实验)
报告指令
- 报告指令控制 CSP违规的报告过程.
- report-uri 当出现可能违反CSP的操作时,让客户端提交报告。这些违规报告会以JSON文件的格式通过POST请求发送到指定的URI(不被推荐)
- report-to 触发SecurityPolicyViolationEvent事件?
其他指令
- block-all-mixed-content 当使用HTTPS加载页面时阻止使用HTTP加载任何资源。
- require-sri-for 使用 SRI 作用于页面上的脚本或样式。
- upgrade-insecure-requests 所有得请求都用HTTPS发起
CSP 和 Workers
- Workers 一般来说不被创建他的文档(或者父级Worker)的CSP策略管理。如果要为Worker指定CSP策略,可以为Worker脚本的请求的响应的头部设置CSP策略。
- 如果Worker脚本的来源是一个全局唯一ID(比如,它的URL是一个结构化的数据或者BLOB)。在这种情况下,这个Worker会继承它所属的文档或者创建它的Worker的CSP策略。
多内容安全策略
- CSP 允许在一个资源中指定多个策略, 包括通过 Content-Security-Policy 头, 以及 Content-Security-Policy-Report-Only 头,和 <meta> 组件(对于相同策略的条款,总是取他们的交集生效)
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/
——————————————————————————————————————————
内容源
- 大多数策略指令需要一个或多个内容源。内容源是一串表明内容可能从哪里加载的字符串。
源列表
- 源列表是一个字符串
- 指定了一个或多个互联网主机(通过主机名或 IP 地址)
- 和可选的 URL 协议和/或端口号。如果端口号没有被指定,浏览器会使用指定协议的默认端口号。如果协议没有被指定,浏览器会使用访问该文档时的协议。
- 站点地址可以包含可选的通配符前缀 (星号, ''),端口号也可以使用通配符 (同样是 '') 来表明所有合法端口都是有效来源。
- 主机通过空格分隔。
http://*.foo.com // 匹配所有使用 http: 协议加载 foo.com 任何子域名的尝试。
mail.foo.com:443 // 匹配所有访问 mail.foo.com 的 443 端口 的尝试。
https://store.foo.com // 匹配所有使用 https: 协议访问 store.foo.com 的尝试。
关键字
- 'none' 代表空集;即不匹配任何 URL。两侧单引号是必须的。
- 'self' 代表和文档同源,包括相同的 URL 协议和端口号。两侧单引号是必须的。
- 'unsafe-inline' 允许使用内联资源,如内联的 <script> 元素、javascript: URL、内联的事件处理函数和内联的 <style> 元素。两侧单引号是必须的。(不安全)
- 'unsafe-eval' 允许使用 eval() 等通过字符串创建代码的方法。两侧单引号是必须的。(不安全)
数据
- data: 允许 data: URI 作为内容来源。这是不安全的,因为攻击者可以精心构造 data: URI 来攻击。请谨慎地使用这个源,并确保不要用于脚本。
- mediastream: 允许 mediastream: URIs 作为内容的源。
- MediaStream 对象代表音频或视频相关数据的流量。 通常一个 MediaStream是作为一个简单的URL string 它可以用来引用存储在DOM中的数据 File, 或者一个 Blob 对象建立 window.URL.createObjectURL()(实验功能)
——————————————————————————————————————————
指令源(以default-src为例)
语法
Content-Security-Policy: default-src <source>;
Content-Security-Policy: default-src <source> <source>;
源
<host-source>
- 以域名或者 IP 地址表示的主机名,外加可选的 URL 协议名(URL scheme)以及端口号。站点地址中可能会包含一个可选的前置通配符(星号 ''),同时也可以将通配符(也是'')应用于端口号,表示在这个源中可以使用任意合法的端口号。
- 举例说明:
- http://*.example.com: 匹配从使用 http: 的 example.com 的任意子域的资源加载。
- mail.example.com:443:匹配对 mail.example.com 上的 443 端口号的访问。
- https://store.example.com: 匹配对使用了 https: 的 store.example.com 的访问。
- 一个网站管理者允许内容来自信任的域名及其子域名 (域名不必须与CSP设置所在的域名相同)
Content-Security-Policy: default-src 'self' *.trusted.com
- 允许网页应用的用户在他们自己的内容中包含来自任何源的图片,
- 音频或视频需从信任的资源提供者(获得)(多媒体文件仅允许从 media1.com 和 media2.com 加载(不允许从这些站点的子域名)。)
- 所有脚本必须从特定主机服务器获取可信的代码.(可运行脚本仅允许来自于userscripts.example.com。)
Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com
- 想要确保网站的所有内容都要通过SSL方式获取,以避免攻击者窃听用户发出的请求。
- SSL(Secure Sockets Layer 安全套接层)
- 该服务器仅允许通过HTTPS方式并仅从onlinebanking.jumbobank.com域名来访问文档。
Content-Security-Policy: default-src https://onlinebanking.jumbobank.com
<scheme-source>
- 协议名如'http:' 或者 'https:'。必须带有冒号,不要有单引号。
- data: 允许 data: URIs 作为内容的源。这是不安全的。攻击者可以注入任意 data: URI 。不要轻易使用这种形式的源,尤其是脚本,绝对不要使用。
data:text/html,<script>alert('hi');</script>
- mediastream: 允许 mediastream: URIs 作为内容的源。
- MediaStream 对象代表音频或视频相关数据的流量。 通常一个 MediaStream是作为一个简单的URL string 它可以用来引用存储在DOM中的数据 File, 或者一个 Blob 对象建立 window.URL.createObjectURL()(实验功能)
- blob: 允许 blob: URIs 作为内容的源。
- filesystem: 允许 filesystem: URIs 作为内容的源。(filesystem: URIs文件系统,已经废弃)
- 禁用不安全的内联/动态执行, 只允许通过 https加载这些资源 (images, fonts, scripts, etc.)
// header
Content-Security-Policy: default-src https:
// meta tag
<meta http-equiv="Content-Security-Policy" content="default-src https:">
'self'
- 指向与要保护的文件所在的源,包括相同的 URL scheme 与端口号。必须有单引号。
- 一些浏览器会特意排除 blob 与 filesystem 。需要设定这两种内容类型的站点可以在 Data 属性中进行设定。?
- 一个网站管理者想要所有内容均来自站点的同一个源 (不包括其子域名)
Content-Security-Policy: default-src 'self'
'unsafe-inline'
- 允许使用内联资源,例如内联 <script> 元素(javascript: URL)、内联事件处理器以及内联 <style> 元素。必须有单引号。
Content-Security-Policy: default-src https: 'unsafe-eval' 'unsafe-inline'; object-src 'none'
'unsafe-eval'
- 允许使用 eval() 以及相似的函数来从字符串创建代码。必须有单引号。
'none'
'nonce-<base64值>'
- 特定使用一次性加密内联脚本的白名单。服务器必须在每一次传输政策时生成唯一的一次性值。否则将存在绕过资源政策的可能。
<script nonce=EDNnf03nceIOfn39fn3e9h3sdfa src=''></script>
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa' // 响应头,指明了nonce白名单包括范围
——————————————————————————————————————————
Strict-Transport-Security
- 一个安全功能,它告诉浏览器只能通过HTTPS访问当前资源,而不是HTTP。(HTTPS一般用来校验身份,随后的请求都换为更节能的HTTP,但是这些请求可能被拦截,然后返回重定向,使你的页面重定向虚假网站,这个响应头强制要求浏览器把HTTP请求转为HTTPS发起)
- 同时阻止了只能通过 HTTP 访问的内容。
语法
Strict-Transport-Security: max-age=<expire-time>
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains
Strict-Transport-Security: max-age=<expire-time>; preload
指令
- max-age= 设置在浏览器收到这个请求后的秒的时间内凡是访问这个域名下的请求都使用HTTPS请求
- includeSubDomains 如果这个可选的参数被指定,那么说明此规则也适用于该网站的所有子域名。
- mail.example.com和calendar.example.com是example.com的两个子域
- preload 不是标准的一部分。(预加载?)
描述
- 一个网站接受一个HTTP的请求,然后跳转到HTTPS,用户可能在开始跳转前,通过没有加密的方式和服务器对话,这样存在中间人攻击潜在威胁,跳转过程可能被恶意网站利用来直接接触用户信息,而不是原来的加密信息。
- Strict-Transport-Security 在通过 HTTP 访问时会被浏览器忽略; 因为攻击者可以通过中间人攻击的方式在连接中修改、注入或删除它. 只有在你的网站通过HTTPS访问并且没有证书错误时, 浏览器才认为你的网站支持HTTPS 然后使用 Strict-Transport-Security 的值 .
浏览器如何处理
- 你的网站第一次通过HTTPS请求,服务器响应Strict-Transport-Security 头,浏览器记录下这些信息,然后后面尝试访问这个网站的请求都会自动把HTTP替换为HTTPS。
- 当HSTS头设置的过期时间到了,后面通过HTTP的访问恢复到正常模式,不会再自动跳转到HTTPS。
- 每次浏览器接收到Strict-Transport-Security头,它都会更新这个网站的过期时间,所以网站可以刷新这些信息,防止过期发生。
预加载 HSTS
- 谷歌维护着一个 HSTS 预加载服务。按照如下指示成功提交你的域名后,浏览器将会永不使用非安全的方式连接到你的域名
- 虽然该服务是由谷歌提供的,但所有浏览器都有使用这份列表的意向(或者已经在用了)。
- 火狐也有自己的 HSTS 预加载列表
示例
- 现在和未来的所有子域名会自动使用 HTTPS 连接长达一年。同时阻止了只能通过 HTTP 访问的内容。
Strict-Transport-Security: max-age=31536000; includeSubDomains