7.7 KiB
Web开发常见漏洞防护
本章介绍web开发时常见漏洞的防护方法
点击劫持
简而言之,点击劫持就是攻击者会自己搭建一个网页,这个网页分为两层:
- 上层是被iframe导入的被攻击网站,具有一些敏感性操作,比如转账、点赞等按钮,这一层会完全透明
- 下层是攻击者自己精心制作的网页,它会准备一个按钮诱导你进行点击(比如点击领取红包等),当你点击这个按钮时,响应你的将不会是这个按钮,而是上层的转账页面,在不知情的情况下造成财产损失
详情介绍参考:https://blog.csdn.net/qq_32523587/article/details/79613768
防范点击劫持的最有效做法就是增加响应头:X-Frame-Options: DENY
, 告诉浏览器我们的网站不可以通过 iframe 进行展示(浏览器收到此响应头的指示之后,会拒绝渲染页面),
从根本上杜绝了点击劫持发生的可能,在 全局过滤器 章节的示例中,我们已经展示了如何在过滤器中增加安全响应头
响应头X-Frame-Options
有三个取值:
DENY
: 任何时候都不可以通过 iframe 展示视图SAMEORIGIN
: 在同域下可以通过 iframe 展示视图ALLOW-FROM uri
: 指定地址来源的访问下可以通过 iframe 展示视图
除了后端的响应头,我们还可以在前端使用如下方式进行判断:
// 判断当前页面是否在顶层视口打开
if(top != window) {
// 跳入一个安全页面,比如404页
location.href="xxx";
}
除了跳转页面,你还可以用其它方法防御点击劫持,比如加载一个全局遮罩来隔离用户的点击操作,或者在非顶层窗口下拒绝提交token,使用户保持未登录状态
XSS攻击
XSS(跨站脚本攻击)就是指攻击者在一段正常的内容中嵌入恶意脚本,使得访问网页的用户自动运行一些破坏性的代码
例如一个论坛具有发帖功能,攻击者在发帖时故意插入一段如下内容:
<img src="xxx" onerror="alert('xss攻击!')" />
如果论坛服务端没有对此进行任何防护,那么用户每次访问这个帖子的时候都会被强制弹窗,
事实上真正的XSS攻击
绝不只是弹窗骚扰一下那么简单,它可以完成窃取Cookie,自动转账等破坏性操作
防范XSS攻击:
- 首先安全响应头给安排上:
X-Frame-Options: 1; mode=block
, 这是浏览器默认提供的XSS防护机制 - 有条件的情况下,尽量使用前后台分离架构,传统服务端渲染视图时几乎每一个变量都可能成为XSS注入点,而前后台分离下一般只有富文本渲染才会有机会XSS注入
- 对所有的用户输入必须XSS过滤,特别是字符串型参数
- 可以使用一些自动扫描工具寻找潜在的 XSS 漏洞
CSRF攻击
CSRF(跨站请求伪造),又称 XSRF,攻击流程如下:
- 用户登陆站点
a.com
,身份令牌被写入Cookie中 - 攻击者搭建站点
b.com
,引诱用户访问 - 用户访问
b.com
时,自动执行了攻击者准备的js代码,即:调用a.com
的转账接口 - 用户在不知情的情况下,造成了财产损失
仅仅访问一个不安全的站点就让我们造成了财产损失?事实上,真正的CSRF攻击并没有这么简单,挡在攻击者第一道门槛便是CORS同源策略
同源策略限制了js在b.com
中只能操作b.com
的数据(Cookie
、localStorage
、DOM
等),而无法直接操作a.com
的数据。
这就导致一个结果:虽然在b.com
可以调用a.com
的转账接口,但是却无法携带用户储存在a.com
的授权Cookie,对于a.com
来讲,即使收到了浏览器发来的请求,
也因为请求中没有携带token令牌,而无法识别调用者具体是谁,只能将其视为一次无效调用。
但是,请注意!这个小小的限制,虽然为用户提供了安全保护,却也为我们开发者造成了不小的困扰,特别是在前后端分离架构下,我们经常会遇到这个错误:
这就是导致无数前端后端互相撕逼的 —— 跨域!
浏览器在检测到你身处b.com
却想要调用a.com
的接口时,会率先发送一个OPTIONS
预检请求,目的是为了询问a.com
是否同意b.com
发起的请求,
在默认情况下,a.com
收到一个陌生的第三方网站发来的请求,做出的回应肯定是:不允许
, 浏览器收到回应就识相的关闭了请求,跨域请求失败
但是,有些开发者为了省事,直接设置了响应头: Access-Control-Allow-Origin: *
,允许任何第三方网站的请求,这就给CSRF攻击
留下了可乘之机
假设我们设置了只允许指定的网站跨域请求,就万事大吉了吗?并没有,攻击者仍可以通过抓包等手段得到我们的转账url,
在b.com
里,通过open(url)
直接打开一个新的窗口调用转账接口,由于是属于打开新页面,浏览器连OPTIONS
预检请求都不会发送,而是直接调用接口成功
此招无解吗?并不。由于它是属于打开新页面,这就导致调用接口时只能发送get请求
,我们在设计接口时只需要遵守一个准则:敏感接口一律post,禁止get调用
即可。
究其原因,导致CSRF攻击
频频发生的原因是什么?是我们在跨域请求时,浏览器总是“自作聪明”的自动提交主站Cookie
,
在浏览器的不断更新中,Cookie的跨域规则变得愈发复杂,新手开发者及其容易绕的晕头转向,而同时w3c
对Cookie
规范的各种修修补补,又总是解决一个问题的同时暴露出其他的N多问题
既然Cookie机制如此难以驾驭,我们何不果断的放弃Cookie机制,改用localStorage
机制存储会话token,这种方式轻松避免了自动提交
带来的各种安全问题。
事实上,localStorage存储
+ header请求头提交
也是前后台分离趋势下的常见会话处理方案
篇幅有限,我们总结一下防范CSRF攻击
要点
在Cookie模式下:
- 仅靠
CORS同源策略
无法彻底防范CSRF攻击
,我们必须在后台建立第三方域名白名单
,只有在白名单中的第三方域名才可以跨域调用我们的接口 - 涉及到数据增删改类型的接口,必须是
post
模式(或其它),严禁get
模式,查询接口可以get
- 敏感操作增加验证码或者二次验证密码,减小被攻击的概率
在 localStorage存储 + header请求头提交 模式下:
- 在配置文件中,配置
is-read-cookie: false
,关闭Cookie模式,防止Sa-Token在登录时注入Cookie - 同上,敏感操作增加验证码或者二次验证密码,减小被攻击的概率
有关CSRF攻防讲解的比较通透的一篇文章:https://juejin.cn/post/6844903689702866952
Token泄露
Token泄露一般发生在客户端,比如用户连接了不安全的WiFi导致通讯被监听,虽然此情形下token泄露的责任在于用户,但是我们还是有必要采取一定的措施使其损失降到最低
- 有条件上https的话一律https
- token有效期一定不能设置为永久,而且要尽量的短(but:为了不影响用户体验又不能设置特别的短,so: 7-30天是个比较合适的范围)
- 对敏感操作接口,增加密码二次校验(或手机验证码等)
- 用户更改密码后使其历史会话直接过期
- 有条件的情况下后台管理增加踢人下线功能,对已经泄露token的账号可以及时清理下线
更多类型漏洞连载中.... (欢迎提交pr)