Web 开发安全 | 青训营笔记
这是我参与「第五届青训营」伴学笔记创作活动的第 11 天
0x1 攻击
-
XSS
Cross-Site Scripting(XSS,跨站脚本攻击)
主要利用了:
- 开发者盲目信任用户提交的内容
- 将用户提交的字符串直接提交到 DOM
特点:
- 通常难以从 UI 上感知
- 窃取用户信息
- 绘制 UI,诱骗用户点击或填写表单
分类:
-
存储型(Stored XSS)
将恶意脚本存放在数据库中,当用户访问页面涉及读取数据时,脚本会被启动,并对全体用户可见
-
反射型(Reflected XSS)
该方法不涉及数据库,而是通过服务端的漏洞,从 URL 上攻击
-
基于 DOM 型(DOM-based XSS)
不需要服务器的参与,恶意攻击的发起和执行都在浏览器上完成
-
基于 Mutation 型(Mutation-based XSS)
该方法利用了浏览器渲染 DOM 的特性,但对于不同的浏览器,具体攻击手段有所区别
-
CSRF
Cross-Site Request Forgery(跨站伪造请求)
特点:在用户不知情的前提下,利用用户权限,构造指定 HTTP 请求,窃取或修改用户敏感信息
-
Injection
Injection(注入)
分类:
- SQL Injection
- CLI
- OS Command
-
DoS
Denial of Services(服务拒绝)攻击通过某种方式(如:构造特定请求),导致服务器资源被显著消耗,来不及响应更多请求,导致请求挤压,进而发生雪崩效应
-
ReDoS(Regex DoS):基于正则表达式的 DoS
正则表达式之贪婪模式
const str = "aaaa"; const gre = /a+/; // 贪婪模式:有多少匹配多少 console.log(str.match(gre)[0]); // "aaaa" const ngre = /a+?/; // 有就行 console.log(str.match(ngre)[0]); // "a"
通过贪婪匹配方法,无限回溯,导致服务器响应时间
++
,接口吞吐量--
-
DDoS(Distributed DoS)
短时间内,来自大量僵尸设备的请求流量,服务器不能及时响应完成全部请求,导致请求堆积,进而发生雪崩效应,无法响应新请求
特点:
- 不限制在域名访问,而是更多的访问 IP
- 不区分接口
-
-
中间人攻击:基于传输层的攻击
即在浏览器和服务器间设置“中间人”(如:恶意网页、路由器等),从而窃取信息、修改请求/返回的数据
主要利用了:
- 明文传输
- 信息篡改不可知
- 对方身份未验证
0x2 防御
-
XSS
- 永远不信任用户提交的内容
- 不要将用户提交的内容直接转换成 DOM
防御工具:
- 前端
- 主流框架默认防御 XSS
- google-closure-library
- 服务端(Node)
- DOMPurify
当发生必须动态生成 DOM 的操作时:
- string 直接生成 DOM 时,须要对 string 进行转译
- SVG 文件上传时,必须进行扫描
- 尽量避免让用户自定义跳转行为,否则须做好过滤
-
CSP
Content Security Policy(内容安全策略)
SOP(Same-Origin Policy,同源策略),判定同源的规则是两个 URL 的协议、域名、端口完全一致
- 允许定义哪些源/域名是被认为安全的
- 来自安全源的脚本可以执行,否则报错
- 对 eval 与 inline script 直接拒绝
举例:
-
服务器的响应头部
... Content-Security-Policy: script-src 'self' Content-Security-Policy: script-src 'self' https://example.com
-
浏览器
<meta http-equiv="Content-Security-Policy" content="script-src self" />
-
CSRF
-
规避伪造请求 原理:如果发现请求来源异常,则可认为其为伪造请求,那么可以通过限制请求来源,从而限制伪造请求
实现:对于请求头部的
Origin
字段和Referer
字段进行校验,若为同源请求,则通过,否则拒绝GET 请求和 HEAD 请求不包含
Origin
字段,因此对Referer
字段的校验更为广泛 -
添加 token 原理:如果请求来自合法页面,那么服务器接收过页面请求,此时服务器可以进行标识
实现:浏览器向服务器请求页面,服务器向浏览器返回页面和 token,之后浏览器向服务器请求 API 与 token,服务器对传回 token 验证通过后返回数据
token 与已注册的用户呈绑定关系。为防止 token 泄露,一般通过设置过期时间来进行前向加密
-
规避 iframe 攻击 原理:通过 CSS 代码,去除 button 的点击事件,使用户的点击操作穿过 button,到达下方隐藏的 iframe,从而伪造了同源请求
实现:修改请求头部的
X-Frame-Options
字段,其有两个值:- DENY:当前页面不能作为 iframe 页面加载
- SAMEORIGIN:必须同源的 iframe 才可以加载
-
anti-pattern
// 将 GET 和 POST 逻辑放在同一各 GET 接口,通过 update 是否有内容来发送不同请求 public async getAndUpdata(ctx) { const { update, id } = ctx.query; if(update) { await this.update(update); } ctx.body = await this.get(id); }
-
SameSite Cookie 原理:由于采用 CSRF 的攻击方式时须要利用用户权限,而用户权限在 Cookie 中,那么当请求中不含 Cookie,则可避免
实现:当向域名 A 发送请求时,对 domain 属性进行判断,若属于该域名,则称之为第一方 Cookie,否则称为第三方 Cookie,只有第一方 Cookie 会被传到服务器中处理。
限制:
-
Cookie domain 属性
-
页面域名是否匹配
当依赖 Cookie 的第三方服务时,可以在服务器端进行操作时,将
Set-Cookie
字段的值设置为SameSite=None; Secure;
与 CORS 对比:
SameSite CORS Cookie 发送 资源读写(HTTP 请求) domain VS 页面域名 资源域名 VS 页面域名 即时处理 设置白名单 总而言之,可以通过设置中间件的方式,对各种 CSRF 攻击进行自适应防御
-
-
-
Injection
对于 SQL 注入:
- 找到项目中查询 SQL 的地方,使用 prepared statement 将 SQL 语句提前编译,避免注入的发生。
对于其他注入:
- 最小权限原则:避免使用 sudo 或 root
- 建立允许名单,并添加过滤:避免出现 rm 等高危命令操作
- 对 URL 类型参数进行协议、域名、ip 等限制:防止访问内网
-
DoS
-
防御 ReDoS
- 避免出现贪婪匹配
- 使用代码扫描工具对代码中的正则表达式进行性能测试
- 拒绝使用用户提供的正则表达式
-
防御 DDoS
主要策略:过滤和抗量
- 流量治理
- 负载均衡
- API 网关
- CDN
- 快速自动扩容
- 非核心服务降级
- 流量治理
-
-
中间人攻击防御
神器:HTTPS(HTTP + TLS)
- 特性
- 可靠性:对明文加密
- 完整性:通过 MAC 验证防止篡改
- 不可抵赖性:通过数字签名确认身份
- 数字签名:私钥加密,公钥检验
HSTS(Http Strict-Transport-Security),用于将 HTTP 请求,升级为 HTTPS 请求
SRI(SubResource Integrity),用于防止静态资源被劫持或篡改
- 特性
Feature Policy / Permission Policy
设置在一个源(页面)下,可以使用哪些功能,如:camera、microphone 等的权限
当页面通过 iframe 的形式加载时,其中的 allow 属性也可以上述功能