前端安全问题实战

2020-08-16  本文已影响0人  般犀

之前公司的安全组扫出了我们官网的几个安全漏洞。安全问题对很多前端来说都是只听过,没见过。这次遇到了真实对漏洞,可以做个记录。

存储型XSS漏洞

XSS,跨站脚本攻击。存储型XSS攻击,即攻击代码被当成文本(如帖子)提交保存到服务器,其他用户打开这段文本的时候,代码就会在其他用户的浏览器里执行。

场景:一个坏人在论坛发布帖子 内容如下:

大家好,第一次在这个论坛发帖,现在我要植入一段代码:<img src=x onerror=alert(1)>

如果论坛没有对帖子的内容做转义处理,直接发布出去。 其他用户点击这个帖子,页面就会插入这个图片标签。由于图片的src异常,图片加载失败,就会触发onerror里的alert。

如果onerror里的内容不是一个简单的alert,而是一段盗取用户cookies的代码呢?那么就会对用户对账户造成威胁。

防御措施

对< > / 符号做escape转义即可,escape可以把所有ASCII 之外的所有字符转换为 %xx 或 %uxxxx(x表示十六进制的数字)的转义序列。

延伸:vue 中 v-html 指令的合理使用

用过 vue 的同学都知道,v-html 的作用是可以把填入 v-html 里的值转化为 html 代码,所以 v-html可能会成为攻击者利用的漏洞,如果把用户提交的内容使用 v-html渲染,就可能会把用户输入的内容变成可执行的代码,形成 XSS 攻击。

反射型XSS漏洞

反射型漏洞:攻击者通过特定的方式来诱惑受害者去访问一个包含恶意代码的URL。
场景还是坏人在论坛发帖,坏人在帖子里贴一个URL,其他用户访问这个URL,使URL上的代码在用户浏览器里被执行。
可能有人会问,在帖子里附带链接不是正常现象吗,用户点击第三方链接导致被攻击跟我有什么关系?
那么,如果用户点击的就是官方链接而触发了XSS攻击呢?

场景:这个发生场景现在来看有点古老了,但大部分网站可能仍会使用的跨域策略:JSONP。
简单描述JSONP的流程:前端使用<script>标签请求后端资源,后端返回的资源会被一个函数包裹,类似:

callback({
  a: 1,
  b: 2
});

而前端会提前在页面定义好这个callback函数,例如:

// 请求到达页面,触发 callback 函数,将资源挂到window上
function callback(res) {
  window.res = res;
}

而通常后台返回的函数名并不会固定返回callback,因为可能会调用到页面其他叫callback的函数,所以,前端在请求的时候,都会在链接后带一个参数,告诉后台,返回的函数名应该叫什么,例如:

前端请求地址:https://xxxxx/giftjson?jsoncallback=mycallback
后台返回结果:

// jsoncallback传的参数是什么,返回的函数名就是什么
mycallback({
  a: 1,
  b: 2
});

可以看到,请求地址上的jsoncallback参数是什么,后台返回的函数名就是什么。看到这句话是不是隐隐感觉到不对劲?如果jsoncallback参数是一段代码呢?

假设,坏人发现了斗鱼直播的一个接口有这个漏洞,在斗鱼论坛发帖:

斗鱼出了个活动啦,大家点击这个链接可以免费抽奖,这个是斗鱼官方链接大家放心点:
https://www.douyu.com/getUserInfo?jsoncallback=<img+src=x+onerror=alert(1)>

其他用户发现这个确实是斗鱼的官方链接就点了进去,结果就运行了jsoncallback里的代码。

防御措施

个攻击其实还需要一点机缘巧合,比如把返回头的Content-Type设置成了application/javascript或者text/html,就会导致字符被当作代码运行。所以防止反射型攻击的方法就是将返回头的Content-Type设置为application/json;即可。

CSRF 攻击

CSRF,跨站点请求伪造。即攻击者在他自己的网站调用你的接口,达到修改你的网站数据的目的。

场景:用户在斗鱼论坛设置了“记住我的登录状态”,于是 douyu.com这个域名下保存了用户的登录cookies。攻击者注意到斗鱼修改用户资料的接口douyu.com/updateUserInfo有CSRF漏洞,于是他伪造了一个斗鱼论坛网站,并做了一个表单:

<html>
<body>
    <form id="csrf" action="douyu.com/updateUserInfo" method="POST">
        <input type="hidden" name="gender" value="2" />
        <input type="hidden" name="hometown" value="1234" />
        <input type="hidden" name="birthday" value="2020&#45;06&#45;11" />
        <input type="hidden" name="nick&#95;name" value="1234" />
        <input type="hidden" name="st" value="123" />
        
    </form>
</body>
<script type="text/javascript">
    function autoSubmit() {
        document.getElementById("csrf").submit();
    }
    autoSubmit()
</script>
</html>

这个表单会提交到douyu.com/updateUserInfo接口,由于用户的浏览器保存了登录的cookies,请求发送出去的时候,用户的登录态也会带出去,斗鱼验证登录态后,确认了是用户本人操作,允许了本次修改。

我们可以发现,通过CSRF漏洞,攻击者伪造了用户的登录态,使修改用户资料的操作成功了。如果本次操作不是修改用户操作,而是转账等危害用户资产安全的操作呢?

防御措施

由此可见,涉及资料修改的操作,仅验证用户登录态是不够的。还需要其他的验证手段:

初级防御措施:判断请求的Referer

请求中的Referer头用于判断该请求是在哪个页面的基础上发出去的,比如a.com请求了一张图片douyu.com/1.jpg,那么图片的Referer头就为:Referer: a.com
上面的攻击场景中,服务器可以判断请求的Referer头,判断该请求是否是官方网站douyu.com发出的,如果不是,则说明是第三方调用,禁止修改。
但是问题是,请求的请求头是可以修改的,攻击者只要将请求的Referer头手动修改为douyu.com,就绕过了这层防御。

进阶防御措施:

  1. token校验
    每个修改资料的请求,都必须携带一个token,而这个token只能在官方网站下生成,提交修改操作的时候,校验这个token是否正确,只有正确才允许修改资料。
    这种验证又叫做“加盐”验证。在表单中混入一个做校验的表单项,用来给服务器做安全校验。

  2. cookies设置Samesite
    设置保存登录态的 cookies 只能在同一个域名的页面下才会随着请求一起发送。这样可以保证cookies不会被第三方使用。但是也多了一个束缚是登录态不能被其他我们受信任的域名共享。
    比如很多单点登录的实现(即如果你在taobao.com登录了,你访问tmall.com的时候,会发现也是登录着的)就是基于 cookies 共享,可能就会收到影响。

上一篇 下一篇

猜你喜欢

热点阅读