前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【安全】 XSS 防御

【安全】 XSS 防御

作者头像
神仙朱
发布2020-02-17 14:54:29
1.3K0
发布2020-02-17 14:54:29
举报
文章被收录于专栏:Vue源码 & 前端进阶体系

后面会把前端进阶的课程内容都总结一遍。有些都是很常见的知识,但是为了梳理自己的知识树,所以尽量模糊的地方都会记录

笔记列表在公众号右下角

首先,我们要知道 XSS 可以做什么,我们才能从根本上杜绝 XSS 攻击

之前的文章也说了XSS 的攻击载体是 恶意脚本,脚本也就是 JS

那么 JS 能做的,恶意脚本都能做

那么 XSS 能利用 JS 做什么呢?

1、窃取用户 cookie。

2、识别用户浏览器。

3、伪造请求。

4、配合钓鱼网站进行攻击

那我们怎么针对上面的手法进行防御,两种方式

1、禁止客户端访问 cookie

2、内容检查

下面来逐个介绍一下

禁止访问Cookie

XSS 不能会窃取用户的 cookie,来假冒用户的登录吗?

那我们就禁止脚本获取 cookie

怎么做?

后端在响应登录时,在 cookie 上设置 httponly

那么此时只有 发送请求时能带上 cookie

脚本是无法读取 cookie 的

我们可以去 调试面板 的 Application 查看 cookie 的 状态

在 cookie 设置了 httponly 之后,然后我们尝试使用脚本获取,发现然并卵了

这么做有什么坏处吗?

恶意脚本不能获取,正常脚本也不能获取了啊,杀敌一千,四损八百,而且并没有根本上解决 XSS,只是减少了 XSS 的发生

因为能走到这一步的,说明恶意脚本还是执行了

就算你不让他获取 cookie,他还是可以做其他事情的

所以我们就有了下一个根本的防御的方法

内容检查

在上面列出的所有 XSS 的攻击手法中,唯一的共同点都是

恶意脚本已经被执行

而我们要做的,应该就是让恶意脚本无法执行,在之前那么多种 XSS 攻击中,什么 反射型,存储型,无非都是原封不动地使用参数

一旦参数是恶意脚本,就惨了,那么就要对 参数 和 输入内容进行检查处理,把可能的出现脚本地方,去掉一些特殊字符,转义特殊字符,变成普通字符,让它不能当做代码去运行

我们主要检测的内容在两个地方

1、输入框

2、url 参数

我们会把输入框的内容放到 url 参数上,又把 url 参数 放到 页面上

所以检查的步骤分为两步

1、输入检查。检查输入框,用户输入的内容

2、输出检查。当把 url 参数 显示到页面上时,需要处理

那么下面我们就按这两个步骤去详细说明

1

输入检查

用户的输入永远是不可信的,需要做过滤和筛选,而一个完善的检查,是需要前端和 后端一起做的

为了避免黑客绕过前端,直接对后端进行请求

输入检查的目的是

1、过滤掉危险字符

比如像 script,javascript,onclick 这种可能带有脚本的词汇

2、转义内容中可能出现的 html 特殊字符

比如标签的 < 转义成 &lt;> 转义成 &gt;

这样就不会把标签当做文本进行处理,而不是html文档

下面记录一个转么转义 html 特殊字符的 方法

代码语言:javascript
复制
*/

网上还有更加完善的方法,这里就是简单记录理解一下,大家在项目中使用时要使用更加完善的方法

2

输出检查

虽然我们已经做了输入检查,但是我们永远要做更多的防御措施,以免有漏网之鱼

并且这一步是防御 XSS 最关键的一步,因为往往就是在这一步,把 恶意脚本插入到文档中

而导致脚本执行,从而发生攻击,所以在我们必须把内容插入到 HTML 文档中时,需要检查 该内容是否 含有恶意脚本

我们一定不能把用户的输入当做是代码运行!!

怎么检查?

检查需要分几个场景去对应处理,就是我们的内容要输出到什么地方

1、输出到 html 标签中

2、输出到 html 普通属性中

3、输出到 html 事件属性中

4、输出到 url 参数中

1输出到 html 标签中

我们把内容,直接拼接在 html 标签上,比如我们的 脚本中有这么一段代码

代码语言:javascript
复制
var username = document.getElementById("username-input").value

其中 username 就是用户的输入的值,然后你直接拼接上html 标签。然后直接插入到文档中

当 username 的值是

代码语言:javascript
复制
'<script>alert(1)<\/script>'

毫无疑问,插入了script 标签,执行了恶意脚本,你就被攻击了

那,要怎么阻止这种行为?

没错,很简单,已经说过了,对一些 html 字符进行转义,方法就是上面给过的 htmlEncode

然后就这么调用

代码语言:javascript
复制
var username = document.getElementById("username-input").value

2输出到 html 普通属性中

如题,就是把内容放进 html 普通属性中

比如你要把内容拼接到一个标签的 id 属性中,如下

document.body.innerHTML = '<span id=" '+str + '"></span>'

其中 str 就是你要输出的内容,然后你把拼接好的内容,直接插入 html 中

当你 str 是

代码语言:javascript
复制
'" > < script>alert(2)</script>'

拼接之后,内容就变成

代码语言:javascript
复制
"<span id="" > <script>alert(2)</script> </span>"

然后~~成功给黑客插入脚本!(~ ̄▽ ̄)~

怎么阻止这种行为?

过滤的方法和 上一个输出到html 标签 是一样的,做法也一样,如下

代码语言:javascript
复制
document.body.innerHTML = '<span id="  '+htmlEncode(str) + '"></span>'

3输出到 html 事件属性中

是不是觉得很疑惑,为什么同样是属性,却要分出 普通属性 和 事件属性两个因为???

事件属性需要要比 普通属性过滤更多的东西,因为他包含的可能不是标签,而是直接运行的脚本

事件属性中的值是可以直接运行的!

比如下面这个操作

代码语言:javascript
复制
` <button onclick="login('`+ phone + `')">  </button> `

目的是把一个绑定了事件的 button 按钮插入到文档中

并且绑定的事件回调是 login, 并传入一个参数用户名,这个参数 phone 就是你要输出的内容了

比如说,现在很多地方需要验证手机号,如下

当你输入手机号正确的时候,就会把获取验证码按钮显示出来

此时就相当于插入一个带有点击事件的 按钮,并且传入手机号发送请求

当这个输入框输入的手机号是一个脚本(假设没有做验证),也就是 phone 的值是一个脚本,如下

代码语言:javascript
复制
"');alert(4);//"

那么拼接之后,就变成这样,点击之后,插入的脚本就运行了~~

document.body.innerHTML =` <button onlick=login("");alert(4);/)"></button> `

把 login 方法给闭合了,并且转义了后面的 括号,在中间插入了脚本

怎么阻止这种行为?

因为他同样是属性,所以过滤两种信息 标签内容 + 脚本内容

标签内容就是 上面说过的两个输出场景,最后附上一个简单方法

代码语言:javascript
复制
function JavasScriptEncode(str){

    function encodeCharx(original){

        var thechar = original.charAt(0);

        switch(thechar){
            case "\n" : return "\\n"; break;
            case "\r" : return "\\r"; break;
            case "\'" : return "\\'"; break;
            case """ : return "\x22"; break;
            case "\&" : return "\\&"; break;
            case "\\" : return "\\\\"; break;
            case "/" : return "\\x2F"; break;
            case "<" : return "\\x3C"; break;
            case ">" : return "\\x3E"; break;
            default: return thechar
        }    
    }

    var preescape= str;
    var escaped = ""

    for(var i = 0; i<preescape.length; i++){
        escaped = escaped + encodeCharx(preescape.charAt(i))
    }

    return escaped
}

4输出到 url 参数中

这个最常见啦,比如在搜索中,就经常把搜索的内容带到 url 参数上

或者电商的商品也是一样的,比如下面的操作

代码语言:javascript
复制
"http://localhost?searchContent = " + content

拼接之后,然后就跳转到这个链接

如果 content 的值是

代码语言:javascript
复制
"<script>alert(1)</script>"

那么链接就带上了恶意脚本

比如页面上需要显示搜索的内容,需要把 searchContent 显示在页面中,那么就把searchContent插入页面中了,所以恶意脚本 script 标签就这么插入页面中,脚本一执行,恶意脚本就触发了

所以我们需要对放上 url 上的参数进行过滤,所幸 JS 内置了一个方法过滤 url,就是encodeURI

我们直接使用就可以了,如下

总结

上面讲了那么多种过滤方式,无非就是要我们不要去相信用户的输入

不管什么时候我们都需要把用户输入的内容进行 XSS 过滤

避免用户的输入是可以运行的代码

所有的过滤都是把可运行的代码变成普通字符,他这个内容变得不可以运行!

最后

鉴于本人能力有限,难免会有疏漏错误的地方,请大家多多包涵, 如果有任何描述不当的地方,欢迎后台联系本人,

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 神仙朱 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
验证码
腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档