**【写在前面】**最近这段时间一直忙公司的安全方面的业务,入网前要做安全测试,所以针对安全测试我就站在前端的角度整理一下,其实我们谈到的安全有以下四个方面:攻击,伪造,注入与越权;这篇文章我们就着重谈一下XSS攻击的场景及我如何处理的方法。

一、概念介绍

XSS攻击(Cross Site Scripting)指代码注入攻击,又名跨站脚本攻击,通过注入恶意的脚本,页面渲染时执行js,可实现盗取用户信息,卡死页面,恶心用户体验等多种效果;

二、场景复现

举个简单的例子吧,如果你存库的数据是一个<script>alert(‘我喜欢黄大大’)</script>,那么在数据显示的时候就会发了疯似的弹窗“我喜欢黄大大”,整的我挺尴尬的;
【安全测试之XSS攻击】安全测试实战之XSS攻击如何应对(基于web)-LMLPHP【安全测试之XSS攻击】安全测试实战之XSS攻击如何应对(基于web)-LMLPHP

三、解决方法

如何解决?(事件监听+正则匹配)

首先看清楚问题的本质,为啥你录入的时候会有这种玩意儿?是因为你提交的数据里面都包含了js脚本的关键词,才会让他在页面上肆无忌惮的喜欢黄大大。
当然之前我们做另一个项目的时候,是针对每个输入框加特殊字符校验,针对系统里面的所有输入框都去看一遍,还得测一遍,关键是废人费力费时间不说,最后还有次测试的时候就因为一个地方没有检测到,导致当时没有通过,你要知道测一次几十万的砸下去,耗不起啊。
吸取前车之鉴,我在统一的公用JS处新增了一个键盘事件,只要键盘抬起我就做判断,如果是输入框的话我就去取里面的值,做特殊字符及关键词(恶意脚本)正则匹配,发现了则去替换掉,具体实现代码如下所示:

$(document).keyup(function(event) {
    debugger;
    //只对input、textarea、td处理
    if($.isNotNull(event.target)&& $.isNotNull(event.target.localName)){
        var localName_str = event.target.localName;
        if($.isNotNull(localName_str) && (localName_str=='input' || localName_str =='textarea' || localName_str=='td')){
            var patrn = /[`@~!#%^&+<>(),\;[\]]/im;
            if(localName_str=='input' && $(event.target).attr("type") == 'password'){
                //密码模块
                patrn = /[`()<>']/im;
            }
            if($.isNotNull($(event.target)) && $.isNotNull($(event.target).attr("validate")) && $(event.target).attr("validate").indexOf("email")>-1){
                //针对邮件的特殊处理,支持@
                patrn = /[`~!#%^&+<>(),\;[\]]/im;
            }
            var inputVal = $(event.target).val();
            var isSpacial = false;
            if(!$.isNotNull(inputVal)){
                //针对td的模式的页面输入框
                inputVal = $(event.target).text();
                isSpacial = true;
            }
            //特殊字符的校验
            if (patrn.test(inputVal)) {
                // layer.msg("输入数据不能包含特殊字符");
                // return false;
                inputVal =  inputVal.replace(/[`@~!#%^&+<>(),\;[\]]+/g,'');
                if(localName_str=='input' && $(event.target).attr("type") == 'password'){
                    //密码模块
                    layer.msg("密码不允许输入特殊字符()<>");
                }else{
                    layer.msg("不允许输入特殊字符");
                }

                if(isSpacial){
                    $(event.target).text(inputVal);
                }else{
                    $(event.target).val(inputVal);
                }
            }
            // 关键词的校验
            var keyWordList = ["script","alert","<a","href","confirm(","prompt(","select","update","delete","drop","insert","and"];
            for(var k=0;k<keyWordList.length;k++){
                if(inputVal.indexOf(keyWordList[k])>-1){
                    inputVal = inputVal.replaceAll(keyWordList[k],"");
                    $(event.target).val(inputVal);
                    break;
                }
            }
        }
    }
});

这里我来说一下为啥我用的是document.keyup哈,我是为了方便监听全局,尤其是有些弹窗的页面都可以达到监听的效果。
另外就是涉及到特殊字符及关键词匹配,特殊字符及关键词替换,提示特殊字符不允许输入三个方面,然后针对具体业务需求自己再加判断,好比邮件录入得有@字符吧。
【安全测试之XSS攻击】安全测试实战之XSS攻击如何应对(基于web)-LMLPHP

四、值得注意

其实这块不只是前端,后端也应该做同样的处理,还有一点就是比较恶心的就是如果人家已经把那种数据通过特定的手段存到你的表里去呢?
那么这个时候就要考虑数据的回显的问题了,针对特殊标签<script、alert(、confirm(等我们就要做一个替换了,这样才能从根本解决页面一直的弹窗;另外你要求更高的话在数据保存入口的地方也可以加上校验,发现有风险的关键词的时候直接去过滤掉,或者用其他字符代替。
**【最后忠告】**个人建议把特殊字符,特殊关键词,整理成配置的文件,前端去读取的方式来做,这样有助于现场调试,省得重新打包了,只要替换配置文件即可,以防特殊字符、关键词的遗漏。

如果觉得这篇文章对您有帮助的话给个小心心哟,后面将介绍有关越权的问题及如何解决的方法!期待您的建议与支持!

11-09 08:04