这是我参与「第四届青训营」笔记创作活动的的第7天。
防御XSS
- Don't trust your user! 不要把用户提交内容直接转换成DOM,先把其当成字符串处理。
- 前端防御:
- 前端主流框架默认防御XSS攻击;
- google-closure-library有提供许多防攻击函数;
- 后端Node防御:
- DOMPurify帮忙完成字符串转义。
- 要是产品需求不讲武德必须生成DOM咋办?
- 对string进行转义,比如使用DOMparser()API
- 用户上传的svg文件也要进行扫描,因为svg中能插入Script。
同源策略
- 两个url上的协议、域名、端口号全部相等。
- 在浏览器中,
<script>、<img>等标签都可以跨域加载,而不受浏览器的同源策略的限制。 - 浏览器同源策略中,除了上述的几个标签可以跨域加载外,其他出现跨域请求时,请求会发到跨域的服务器,并且会服务器会返回数据,只不过浏览器拒收返回的数据。
Content Security Policy内容安全策略(CSP)
- 看哪些源(域名)被认为是安全的。
- 来自安全源的脚本可以执行,否则直接抛出错误。
- 对eval或者内联inline的Script标签报错。
- demo:在服务器响应头部中:限制所有外部资源,所有资源只能从当前域中加载。
Content-Security-Policy:default-src "self" - 若只有脚本在当前域中加载:
Content-Security-Policy:script-src "self" - 浏览器meta中:
<meta http-equiv = "Content-Security-Policy" content = "default-src self">
CSRF防御
Origin和Referer
- 可以通过验证验证HTTP的Origin和Referer。
- 在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。
- demo:比如银行网站只需要对于每一个转账请求验证其 Referer 值,如果域名以银行自己开头,则说明该请求是来自银行网站自己的请求。如果 Referer 是其他网站的话,则拒绝该请求。
token验证
- 当浏览器向服务器请求页面时,服务器返回带有Token的URL页面,浏览器在该页面请求API时需携带token验证,若验证通过通过请求返回验证后token和请求结果。
- token需要和具体用户自己账号绑定才能确保不被其他注册用户利用。
- token需要有过期时间,防止用户token被窃取后暴露用户请求信息。
预防iframe攻击
- 攻击者网站下有个去往被攻击网站下的按钮(被Iframe包裹着的按钮),用户点击时向被攻击者网站发送请求,在被攻击网站看来是同源请求。
- 模拟:
<div> <!-- iframe包裹我们合法页面 --> <button onclick = "event1"></button> <!-- button伪装 --> <div onclick = "event2"></div> <!-- 其实触发的是隐藏事件 --> </div> - 解决方案:
- 在服务器中配置添加X-Frame-Options响应头,可赋值为:DENY/SAMEORIGIN。
SameSite Cookie
- 避免用户信息被携带。
- demo:在域名A下的cookie称为第一方cookie,不是A域名下的cookie为第三方cookie,当向域名A发出请求时,第一方Cookie是可以被带走的,而第三方Cookie不被带走。
- SameSite属性可以设置三个值:Strict、Lax、None。
Injection防御
- 找到项目中查询SQL的地方,使用prepared statement,即提前编译。
防御DoS
- 避免写出贪婪匹配的方式。
- 扫描代码中的正则表达式并进行规整。
- 拒绝用户提供的正则表达式。
传输层:防御中间人
- HTPS(HTTP+TLS)特性:
- 可靠性:加密。避免明文传输。
- 完整性:MAC验证。确保信息未被篡改。
- 传输内容 = 加密信息+加密信息hash
- 接收方中:if(hash(加密信息) === 加密信息hash)那就可行,即信息没有被篡改
- 不可抵赖性:数字签名。确保双方身份可被信任。
- 签名执行者会有一对私钥和公钥,数字签名 = 私钥+内容
- 公钥验证签名:如果是用自己对应私钥的签名,则校验通过。
- 数字签名在HTTPS工作:
- 每一个主流浏览器都会内置大量CA签发证书。
- 如何将HTTP升级成HTTPS请求:
- 浏览器向服务端发送HTTPS请求,服务端向浏览器发送HTST(Strict-Transport-Security)并附带时间限制,在时间范围内,若浏览器发出HTTP请求,则自动升级成HTTPS协议,阻止了中间人攻击。
SRI:静态资源被劫持篡改怎么办?
- 浏览器加载静态资源时,会对Script标签中的integrity属性哈希算法进行计算,对计算出哈希后进行对比,若哈希值相同则说明资源没有被篡改。
<script src = "XX.js" integrity = "sha384-{hash-value}" crossorigin = "anonymous" ></script>const remoteHash = hash(content) if(tagHash != remoteHash){ //被篡改了! }