谈谈对 Web 安全的理解
Category(分类): Other Status: 已读
原文:谈谈对 Web 安全的理解(知乎专栏,Lindz,2017-03)。 知乎页面反爬无法直接抓取,本文以作者同步发布于掘金的同款文章(juejin.cn/post/6844903465961947150)为底本整理,内容一致。 作为一个前端 er,掌握必要的网络安全知识是必要的,本文整理几种常见的网络攻击方式及防御技巧。
一、CSRF 攻击
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为 one click attack / session riding,缩写 CSRF/XSRF。
CSRF 可以简单理解为:攻击者盗用了你的身份,以你的名义发送恶意请求,容易造成个人隐私泄露以及财产安全。
要完成一次 CSRF 攻击,受害者必须完成:
- 登录受信任网站 A,并在本地生成 Cookie;
- 在不登出 A 的情况下,访问危险网站 B。
GET 版攻击
某银行网站 A 以 GET 请求完成银行转账:
http://www.mybank.com/transfer.php?toBankId=11&money=1000
而危险网站 B 的页面中含有:
<img src=http://www.mybank.com/transfer.php?toBankId=11&money=1000>
某天你登录了银行网站 A,然后又访问了危险网站 B——你的银行账号就少了 1000 块。原因是银行网站 A 违反了 HTTP 规范使用 GET 更新资源:B 中的 <img> 以 GET 方式请求第三方资源,由于你此前登录 A 且还未退出,浏览器会带上 A 的 Cookie 发出请求,银行服务器认为这是一条合法的更新操作,立刻转账。
POST 也防不住
银行把接口改成只接受 POST 后,危险网站 B 同样与时俱进——用一个隐藏的自动提交表单照样发 POST:
<body onload="steal()">
<iframe name="steal" display="none">
<form method="POST" name="transfer" action="http://www.myBank.com/transfer.php">
<input type="hidden" name="toBankId" value="11">
<input type="hidden" name="money" value="1000">
</form>
</iframe>
</body>
可以看出,CSRF 攻击源于 WEB 的隐式身份验证机制!WEB 的身份验证机制虽然可以保证一个请求是来自某个用户的浏览器,但无法保证该请求是经过用户批准发送的。
CSRF 防御
CSRF 防御可以从服务端和客户端两方面着手,从服务端着手效果比较好(现在一般也都在服务端进行):
- 关键操作只接受 POST 请求(基础防线,如上所示单靠它不够);
- 验证码:CSRF 攻击往往在用户不知情的情况下发生,验证码强制用户互动,简单有效。但任何操作都要验证码会严重影响体验,所以一般只用于特殊操作或注册;
- 检测 Referer:页面与页面之间存在联系,通过检查 Referer 的值可以判断请求来源是否合法。但问题在于服务器不是任何时候都能收到 Referer(客户端可能不发送),所以 Referer Check 一般用于监控 CSRF 攻击的发生,而不是抵御攻击;
- Token(主流做法):CSRF 攻击成功的条件在于攻击者能够准确预测所有参数从而构造合法请求。根据不可预测性原则,额外添加一个随机参数 Token,攻击者因不知道 Token 而无法构造合法请求。Token 的三个要求:
- 足够随机,使攻击者无法准确预测;
- 一次性,每次请求成功后更新,增加预测难度;
- 注意保密性,敏感操作使用 POST,防止 Token 出现在 URL 中。
最后值得注意的是:过滤用户输入的内容不能阻挡 CSRF 攻击。我们要做的是过滤请求的来源——有些请求合法、有些非法,CSRF 防御主要是过滤那些非法伪造的请求来源。
二、XSS 攻击
XSS 又称 CSS(Cross-site script,跨站脚本攻击),为与层叠样式表 CSS 区分而取名 XSS,是 Web 程序中常见的漏洞。
其原理是攻击者向有 XSS 漏洞的网站中输入(注入)恶意 HTML 代码,当其他用户浏览该网站时,这段代码会自动执行,从而达到攻击目的:盗取 Cookie、破坏页面结构、重定向到其它网站等。
例如某论坛的评论功能没有对 XSS 进行过滤:
<script>
while(true) {
alert('你关不掉我');
}
</script>
服务器没有过滤或转义这段脚本,作为内容发布到页面上,其他用户访问时就会运行。这只是个玩笑级示例,恶意者把代码换成窃取 Cookie 的脚本,危害立刻升级。
XSS 的两种类型
- 持久型 XSS:攻击脚本植入到服务器上(如上述留言评论),所有正常访问的用户都会遭到攻击;
- 非持久型 XSS:对页面 URL 的某个参数做文章,把恶意脚本包装在 URL 参数中,再将 URL 发布到网上骗取用户点击。
非持久型威胁较小——服务器调整业务代码过滤后,精心构造的 URL 瞬间失效;持久型影响力很大,服务端有时要删好几张表、查很多库才能清除恶意数据。
XSS 防御
理论上,所有可输入的地方只要没对输入内容处理,都存在 XSS 漏洞。最简单直接的方法是过滤用户输入:
- 不需要用户输入 HTML 时:直接对输入做 HTML 转义:
<script>window.location.href="http://www.xss.com";</script>
转义后:
<script>window.location.href="http://www.xss.com"</script>
它变成普通文本显示出来,无毒无害不能执行。
- 需要用户输入 HTML 时(如富文本):要更小心细致地处理。仅仅粗暴去掉
<script>标签是没有用的——任何合法 HTML 标签都可以添加onclick一类的事件属性执行 JS。更好的方法是:用 HTML 解析库解析用户输入,获取数据后按原有标签属性重建 HTML 元素树,重建过程中所有标签、属性只从白名单中拿取。
三、SQL 注入
所谓 SQL 注入,就是把 SQL 命令插入到 Web 表单提交或页面请求的查询字符串,最终欺骗服务器执行恶意的 SQL 命令。
它利用现有应用程序,将(恶意)SQL 命令注入到后台数据库引擎执行,通过在表单中输入恶意 SQL 语句,直接获取存在漏洞的网站数据库数据,而不是按照设计者意图执行。
SQL 注入防护
- 永远不要信任用户的输入:对输入校验(正则表达式、限制长度),对单引号和双
--进行转换等; - 永远不要使用动态拼装 SQL:使用参数化的 SQL 或直接使用存储过程进行数据存取;
- 永远不要使用管理员权限的数据库连接:为每个应用使用单独的、权限有限的数据库连接;
- 不要把机密信息明文存放:加密或 hash 掉密码和敏感信息。
四、DDoS 攻击
分布式拒绝服务(Distributed Denial of Service)攻击借助客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目标发动攻击,成倍提高拒绝服务攻击的威力。
打个比方:一群恶霸试图让竞争对手的商铺无法正常营业——扮作普通客户一直拥挤在商铺里赖着不走,真正的购物者无法进入;或者总跟营业员东扯西扯,让工作人员不能正常服务;也可以提供虚假信息让商铺上上下下忙成一团却发现是一场空。恶霸们单干难成事,需要叫上很多人一起——DoS 和 DDoS 攻击就遵循这些思路。
DDoS 攻击利用目标系统网络服务功能缺陷或直接消耗其系统资源,使目标系统无法提供正常服务——通过大量"合法"请求占用大量网络资源,达到瘫痪网络的目的。具体形式有:
- 使网络过载,干扰甚至阻断正常的网络通讯;
- 向服务器提交大量请求,使服务器超负荷;
- 阻断某一用户访问服务器;
- 阻断某服务与特定系统或个人的通讯。
五、SYN 攻击
SYN 攻击属于 DDoS 攻击的一种具体表现形式,利用 TCP 三次握手的机制缺陷:
三次握手过程中,服务器发送 SYN-ACK 之后、收到客户端 ACK 之前的 TCP 连接称为半连接(half-open connect),此时服务器处于 SYN_RCVD 状态,收到 ACK 后才转入 ESTABLISHED。
SYN 攻击指的是:攻击客户端在短时间内伪造大量不存在的 IP 地址,向服务器不断发送 SYN 包;服务器回复确认包并等待客户确认。由于源地址不存在,服务器需要不断重发直至超时——这些伪造的 SYN 包长时间占用未连接队列,正常 SYN 请求被丢弃,导致目标系统运行缓慢,严重者网络堵塞甚至系统瘫痪。
检测:非常方便——当服务器上出现大量半连接状态,特别是源 IP 地址是随机的,基本可以断定是 SYN 攻击。
防护:
- 缩短超时(SYN Timeout)时间;
- 增加最大半连接数;
- 过滤网关防护。
参考资料
整理者注
本文是"一句话讲透原理 + 一个例子 + 一组防御清单"风格的 Web 安全入门总览,与本分类另外几篇互为补充:
- XSS/CSRF 的深度专项:见《前端安全系列(一):如何防止XSS攻击?》《前端安全系列(二):如何防止CSRF攻击?》(美团技术团队,含现代浏览器 SameSite Cookie 等新防御);
- JSONP 相关风险:见《前端也需要了解的 JSONP 安全》;
- 综合版:见《你必须要懂的 Web 安全》。