防御XSS攻击
- 永远不信任用户提交的内容
- 不要直接将用户提交的内容转换成DOM,应该直接当作string对待
防御XSS的现成工具
前端
- 主流框架(Vue,React)默认防御XSS
- google-closure-library ,提供了防御XSS的工具函数
服务端(Node)
- DOMPurify(npm包)
如果实际需求中必须动态生成DOM,如接收用户传送的富文本并生成DOM
string -> DOM
将string直接生成DOM
// 调用Parser API将string直接生成DOM,注意需要对string进行转义
new DOMParser()
上传svg
允许用户上传svg文件
需要对svg文件进行扫描,按照规范svg中可以插入script标签
如果svg图片被加载,script标签会被加载,即完成一次XSS攻击
<svg>
<script>alert("xss")</script>
</svg>
Blob动态生成 script
尽量不让用户做自定义跳转的行为,自定义跳转链接可以携带Javascript 代码
下图中实例化Blob中的script 可以是一段 JS 代码,通过以下代码,生成的 url 将被赋值给<script>元素的src属性,然后将该<script>元素添加到文档的<head>元素中。这样,动态生成的JavaScript脚本将被加载和执行。
自定义样式导致XSS攻击
允许用户自定义样式也可能导致XSS攻击,须注意图片,字体文件等可以设置url的地方
下图中,只有当某个radio标签被选中时,才会触发一个背景图的 get 请求
即只有指定收入的用户选择时才会发送get请求,如此该用户的收入情况就被暴露给攻击者了
Same-origin Policy 同源策略
需要协议,域名,端口号均相等,才算同源
一般而言对于http请求,默认支持同源请求,对于跨域请求需要额外设置服务器
Content Security Policy(CSP) 内容安全策略
一种用于增强网页安全性的浏览器机制。它通过定义、限制或禁止某些特定来源和类型的资源加载,帮助减少跨站脚本攻击(XSS)、数据注入和点击劫持等常见的安全漏洞。HTTP中的CSP ( Content Security Policy )内容安全策略 - 掘金 (juejin.cn)
- 允许开发者定义哪些源(域名)是安全的
- 来自安全源的脚本可以执行,否则直接报错
- 可以对 eval + inline script (内联的script) 直接报错
服务器的响应头部设置
// 同源
Content-Security-Policy: script-src 'self'
// 在同源之外还允许了另一个域名的script执行,其他的域名都不可以
Content-Security-Policy: script-src 'self' http://doamin.com
浏览器的meta设置
<meta http-equiv="Content-Security-Policy" content="script-src self">
CSRF(跨站伪造请求) 的防御
Origin + Referer
请求来源异常,对请求的origin和referer进行校验,如果请求来源是指定的域名就放行
另:同源请求中,GET 和 HEAD 请求不会发送 Origin字段,所以 referer一般会被更广泛的应用
CSRF——token
注意:token需要和具体用户进行绑定,才能确保不被其他的注册用户利用
token 需要有过期时间
CSRF——iframe 攻击
攻击者会构造一个页面,页面上有一个button标签,button标签下面会盖着一个 iframe ,当用户点击这个button标签的时候,由于button标签设置的 CSS 属性,导致点击行为被穿越到下方的 iframe 之中,此时iframe 可能因为受到了点击,而发起一个 http 请求,又因为 iframe 发起的请求不是跨域请求,是同源请求,因此请求不会被拒绝,攻击完成
预防iframe攻击可以设置X-Frame-Options 响应头
DENY:拒绝将网页加载到任何<frame>或<iframe>中,无论来源是否相同。SAMEORIGIN:只允许将网页加载到与网页本身具有相同源(同源)的<frame>或<iframe>中。
X-Frame-Options是一个 HTTP 响应头,用于保护网页免受点击劫持(Clickjacking)攻击。通过设置适当的X-Frame-Options值,可以控制浏览器是否允许将网页加载到<frame>或<iframe>元素中。点击劫持:攻击者将恶意网页覆盖在正常网页上,当用户点击页面上的按钮或链接时,实际上会触发隐藏的恶意操作。
CSRF anti-pattern 反模式
下面的代码中将 get 的请求实现为既能 get 又能 post,即既能获取数据,又能修改数据。
这样的话,如果会被 CSRF 攻击到,那不仅是用户隐私可能被泄露,甚至用户的隐私都可能被窜改,攻击者一石二鸟。
避免用户信息被携带: SameSite Cookie
如果 CSRF 利用的是用户权限,而用户权限又在 cookie 之中,又如果请求不带上这个 cookie ,就无法实现跨站伪造请求。
即一个页面的 cookie 只能由对应的源(origin)使用,其他页面向发出的请求都不能带上这个 cookie,也就从根源上解决了CSRF攻击。
假设有一个页面,页面对应的域名是A,那么此时所有 domain 属性是 A 的 Cookie ,都称之为第一方 Cookie ,也就是 SameSite Cookie 。所有 domain 属性不是 A 的 Cookie ,全部归为第三方 Cookie ,也就是非 SameSite Cookie 。
当向域名 A 发出请求时,所有第一方的 Cookie 都会被带上,所有第三方的 Cookie 都不会带上,这也是浏览器的默认行为。
SameSite Cookie限制的是Cookie的domain属性和当前页面的域名是否匹配
Chrome 51 开始,浏览器的 Cookie 新增加了一个
SameSite属性,用来限制第三方 Cookie,防止 CSRF 攻击和用户追踪,从而减少安全风险。
依赖Cookie的第三方服务怎么办?
在服务器端进行 Set-Cookie 操作的时候,可以把 SameSite 这个属性标志为 none,也就是说不对 SameSite 进行任何限制,但同时我们需要标明这个 Cookie 是 Secure 的,以确保安全。
SameSite vs CORS
- SameSite针对的是Cookie的发送,CORS针对Http请求进行限制
- SameSite对比的是Cookie的domain属性与当前域名是否一致,CORS对比的是资源域名与页面域名是否一致
- SameSite一旦离开当前页面,其他页面的请求将无法带上这个 Cookie,CORS 更接近于白名单的机制,我允许你访问你才能访问
SameSite demo
防御CSRF 的正确姿势
针对Injection注入攻击的防御方式
- 找到项目中查询 SQL 的地方
- 使用 prepared statement
prepared statement :将SQL 语句提前编译,导致injection攻击不能完成
Injection beyond SQL
-
最小权限原则
- 所有的命令都不要通过 sudo 来执行,不要给 root 权限
-
建立白名单机制,只允许指定命令的执行
- rm这种高危操作,是要坚决拒绝的
-
针对 SSRF 攻击方式,要对URL上的参数类型、协议、域名、IP进行限制
- 避免攻击者访问内网资源,造成内网系统瘫痪
防御 DoS
- 避免写出贪婪匹配的正则表达式
- 通过代码扫描的方式规整正则表达式,并进行性能的基础测试
- 拒绝使用用户提供的正则
防御 DDoS
- 流量治理:在负载均衡或 API 网关层进行一些流量识别,把识别出的恶意攻击进行过滤,将它们转到其他服务或者直接拒绝。
- 前置 CDN :所有流量都要先经过CDN,再到具体的服务
- 快速自动扩容:当服务检测到流量激增时,可以自动执行快速扩容的操作,以承载更多的流量
- 非核心服务降级:所有非核心业务功能统统降级(关闭),以匀出更多的计算资源去应对激增的流量
针对传输层的防御方式 —— 防御中间人
针对传输层的防御方式主要就是防御中间人
下图中展示的是最新版本的HTTP3,其内置了TLS,后续的内容将不基于此版本
HTTPS 的一些特性
- 可靠性:运用加密,避免了明文传输,
- 完整性:运用 MAC 校验规则,确保信息没有被篡改
- 不可抵赖性:运用数字签名,确保了双方的身份是可被信任的
HTTPS 或 TLS 的大致流程(简略版本)
- 非对称加密
- 对称加密
先进行非对称加密过程,浏览器会先把自己支持的加密套件选项传给服务端,服务端接受这个可支持的加密套件选项后,会选一个具体的套件,并且把服务器端的证书,返回给浏览器。浏览器先将证书进行校验,如果证书校验通过,那么双方会根据之前协商好的加密算法以及一些额外的随机数等,算出一个 sessionKey,此时非对称加密过程结束。
之后进入对称加密过程,双方使用 sessionKey 作为 secure,对所有的信息进行对称加密,所有的传输信息都是加密后的信息,这就是一次完整的TLS过程。
HTTPS——完整性
传输的信息,会额外传递一个加密信息对应的 hash 哈希值,接收方会对加密的信息进行计算得到一个新的哈希值,将新的哈希值与传递过来的哈希值进行比较,如果两者相等,说明没有被篡改,不等则说明信息被篡改。
HTTPS——不可抵赖:数字签名
https的不可抵赖性是靠数字签名来保证的
数字签名
数字签名使用其私钥,对指定内容进行数学计算,并生成对应的签名,具备公钥的人可以运用公钥对生成的签名进行校验
-
HTTPS 在非对称加密过程中会传递证书,存在一个 CA 证书机构,证书机构会完成一些签名的操作。
比如说:服务的提供方会把它的一些元信息以及一些公钥合并成一对信息,然后使用 CA 提供的一对私钥进行签名,生成真正的服务器端保存的证书,这个证书就会传递给浏览器层。浏览器就会用 CA 颁发的公钥,对这个证书进行校验。如果校验通过,说明这个证书合法,也就是证书签发者的身份是可信的,这也就是完成了一次数字签名校验的流程。
-
那浏览器是如何有 CA 的公钥的呢?
实际上每一个主流的浏览器都会内置大量 CA 签发证书,这些证书里面就会包含 CA 各个的公钥
-
成也证书,败也证书。
当签名算法不够健壮时,证书可以被破解和造假的,也就导致了中间人又有可乘之机,但好在签名算法不断地迭代,以及 CA 方不断地更新迭代,现在的签名算法已经非常的健壮,以及非常难以通过单一的一个攻击者暴力破解,现在可以非常放心的使用证书。
HTTP Strict-Transport-Security(HSTS)
将 HTTP 请求升级为 HTTPS
简单流程:首先浏览器向服务器端发送一个 Https 的请求,服务器端接受到这个请求后会返回 Strict-Transport-Security 这个头部,并且传递一个值 max-age=3600 ,即在这个时间范围内,之后如果浏览器发出的是 http 请求,那么统统升级为 Https 协议,也就确保了之后,不会再因为用户手动输入 http,而导致潜在中间人攻击。
缺点:一定要先有一次 https 请求。
Subresource Integrity(SRI)
- 前端工程开发会把很多的静态资源,比如 js,css,... 文件,放到 CDN (一个静态资源托管的地方),如果 CDN 被攻击者攻陷,导致我们所有的资源被劫持,被篡改,那么怎么办呢?
-
通过 SRI 解决。SRI 的功能实际上就是对比哈希值 hash,确保在CDN上托管的资源不被篡改
- 标签 hash(原始内容hash)vs 实际内容 hash
左侧是实现SRI 的方式,在script标签上增加一个integrity属性,这里标明了摘要值的算法以及具体的摘要值,当浏览器发出请求拿到资源并下载完毕后,会对真实的资源进行hash计算,计算后与integrity上的hash值进行比较,若结果相同,则表明资源没有被篡改,若不同则被篡改,存在被攻击了的风险
补充内容
Feature Policy / Permission Policy
特性策略(Feature Policy)和权限策略(Permission Policy)是为了增强浏览器安全而引入的两个机制。
- 特性策略:允许网站控制其在浏览器中可用的功能和API。通过在 HTTP 头部或 HTML 标签上设置特性策略,网站可以限制或禁止某些功能的使用,以减少潜在的安全风险。例如,可以禁用摄像头、麦克风、地理位置等敏感的设备或功能,防止恶意网站滥用用户的权限。
- 权限策略:是控制网站在其他域上执行脚本或加载资源的一种机制。通过在响应头部设置权限策略,网站可以限制或允许其他域加载其内容。这在防止跨域资源共享(CORS)攻击和数据泄漏方面非常有用,因为它可以限制哪些源可以加载网站的资源,并且可以细粒度地控制可访问的源。
如果被XSS攻击了,可以限制页面不可以调用一些敏感的功能(如相机麦克风等)
如果页面是通过iframe形式加载的,iframe提供的allow属性也可以实现类似的功能