打造一个自动检测页面是否存在XSS的插件Ⅲ

2015-09-22 381231人围观 ,发现 14 个不明物体 WEB安全

本文原创作者:Black-Hole

前言

本章主要是对“form表单XSS检测”进行介绍,以及对反馈页面的修改。上一章我就说过“form表单XSS检测”有点复杂。

所以我就重新开了一章来写,也就是这章。关于代码的构架,请移步到FreeBuf之前文章《打造一个自动检测页面是否存在XSS的插件Ⅱ》的第0×01和0×02小节。本章就不涉及代码构架了。

0×01 检测思路

先判断页面是否存在form表单,如果不存在,则不运行相关的检测代码。当页面存在form表单时,则过滤出正确符合条件的form表单,满足下面的条件:

一、Form表单里如果存在img标签,则判断src属性值,查看后缀是是否为jpg、png、jpeg、gif,如果不为这些后缀,说明是“验证码”返回false,因为存在“验证码”的form表单,ajax发送会出错,因为我们不知道获取“验证码”的值。
二、form标签必须存在input的type属性为submit的标签,text、password、radio、checkbox这些必须要有一个存在才可以。

上面筛选的结果只是最初的筛选结果,还需要判断form表单里的input是否存在name值,不然无法构造ajax发送的数据。

然后就是发送了。“form表单XSS检测”主要就是筛选出正确符合条件的麻烦。还有发送时数据的处理也比较麻烦。

0×02 测试环境

根据上面的检测思路,我们需要一个符合思路的测试环境。如下:

一、需要一个form表单里存在图片,而且可以触发XSS。
二、需要一个form表单里存在图片,不可以触发XSS。
三、需要一个form表单里存在以“动态文件”(验证码图片)为后缀的form表单。
四、需要一个没有图片,可以触发XSS的form表单。
五、需要一个没有图片,不可以触发XSS的form表单。

测试环境代码如下。

存在图片,而且可以触发XSS:

<form method="post">
    <input type="text" name="xss">
    <img src="https://image.3001.net/images/new/logo.png" alt="">
    <input type="submit">
</form><br><hr>

存在图片,不可以触发XSS:

<form method="post" action="http://baidu.com/">
    <input type="text" name="xss">
    <img src="http://loudong.360.cn/images/logo.png" alt="">
    <input type="submit">
</form><br><hr>

存在以“动态文件”(验证码图片)为后缀的form表单:

<form action="#" method="post">
    <input type="text" name="xss">
    <img src="http://passport.360.cn/captcha.php?m=create&app=i360&scene=login&userip=ra6YBkHL%2B8G6xqIXmQwvKw%3D%3D&level=default&sign=818d50&r=1441020794&_=1441020960160">
    <input type="submit">
</form><br><hr>

没有图片,可以触发XSS的form表单:

<form  method="get">
    <input type="text" name="xss">
    <input type="text" name="caonima">
    <input type="submit">
</form><br><hr>

没有图片,不可以触发XSS的form表单:

<form  method="get" action="http://360.cn/">
    <input type="text" name="asd">
    <input type="text" name="wocaonimabi">
    <input type="submit">
</form>

效果如下:

光写html代码可不行,没有输出怎么办,下面是PHP输出的代码:

<?php
    if(isset($_POST['xss'])){
        echo $_POST['xss'];
    }
    if(isset($_GET['a'])){
        echo $_GET['a'];
    }
    if(isset($_GET['caonima'])){
        echo $_GET['caonima'];
    }
?>

0×03 函数变量

建立一个名为form_Xss函数function form_Xss(){…}

下面是form_Xss函数里的变量:

var tureForm;     //存放符合条件的form表单数据
var tureInput;        //存放符合条件的input标签数据
var formImg;      //form表单里的img标签里的src属性值后缀
var actionUrl;        //form表单的action属性的值
var methodType;   //form表单的method属性的值
var sendDataUrl;  //发送时的URL
var i;             //第一层for循环的初始变量
var j;             //第二层for循环的初始变量

0×04 form表单筛选

在0×01节说了那么多的判断,就是要筛选符合正确条件的form表单,这里我们不能一直都用for{if…eles…}来完成,太费时间,效率也不高。幸好在JavaScript里,提供了filter这个函数,这个函数会对数组中的每一项都给定一个函数,返回以ture为结果的数组,例如:

var numbers = [1,2,3,4,5];
filterNubmbers = numbers.filter(function(item,index){
return (item > 3)
})

会返回number数组里,所有大于3的数组,然后返回一个新的数组,上面的执行结果如下:

item是数组里的项,index是项在数组里的位置。

这里有个坑,后面会遇到,这里说明一下。

fliter函数是提供给Array的,也就是Array.fliter(function(item,index){…}),但是也可以使用Object。也就是Object.filter(function(item,index){…})

只是当为Object对象时,item和index会互换。前面说到item是数组里的项,但是当为Object时,item就是项在数组里的位置,index才是数组里的项。切记,切记,切记。

前奏说完了,开始进入正题。

我们需要获取form表单,再进行判断。于是代码就如下:

tureForm = $("form").filter(function(item,index){});

Jquery返回的是“Object对象”这点切记,也就是说什么的filter其实是对象。那item和index就已经互换了。下面的index就是数组里的项,也就是页面中每一个form表单数据。我们打印看下:

接下来就是获取form里面的img标签里的src属性:

formImg = $(index).find("img").attr("src");

forImg现在就等于img标签里src的值了。下面就是做判断是否存src这个属性:

if(!!formImg){    /*当存在src属性时,运行代码*/ }else{
   /*当不存在src属性时,运行的代码*/
}

!!的作用将后面的forImg强制转换为布尔类型的数据。方便if判断。

这里我们还需要一个if,因为很多的网站,为了防止浏览器对图片进行本地缓存(防止图片无法第一时间更新)而在图片地址后面加上随机参数。我们现在就使用if来去掉这些随机参数。因为随机数一般都是类似这样:

http://www.freebuf.com/logo.png?rand=012350154453

这里我们就要去掉?rand=012350154453,只留下http://www.freebuf.com/logo.png字符串。代码如下:

if(formImg.indexOf("?") != "-1"){
    formImg = formImg.slice(0,formImg.indexOf("?"));
}

当存在"?"字符串时,则删除?后面的字符串,留下删除后的字符。如下图:

这样一来,就去掉了随机数,接下来就是获取文件的后缀名了。

formImg = formImg.substr(formImg.lastIndexOf("."),formImg.length);

formImg.lastIndexOf(".")是substr函数的第一个参数,计算formImg字符串从后开始第一个"."的下标位置,为什么不用indexOf呢,因为去掉参数后,后缀也就只有几个字符,而前面则是非常多的字符串。这样一来,速度快一些。获取从最后开始出现的"."字符。而且url地址都会有.。比如freebuf.com或者127.0.0.1这样获取的字符串就不准确了。

formImg.length则是formImg变量的长度,也就是去掉参数的图片地址有多少个字符串。

formImg = formImg.substr(formImg.lastIndexOf("."),formImg.length);这一段代码就完成了获取后缀的功能,我们开输出看下:

获取后缀后,接下来就是判断后缀是否符合条件了:

if(formImg == ".png" || formImg == ".jpg" || formImg == ".jpeg" || formImg == ".gif"){
    /*当符合上面的条件时,运行代码*/
}

||管道符的作用是,当前为false时,再判断后面的。说详细点就是:

先判断获取的后缀是否为png,如果不为png则再判断是否为jpg,如果不为jpg再判断是否为jpeg,如果不为jpeg判断是否为gif。如果都不是,则不运行代码。至于else就不用写了。为什么呢?因为当没有return时,JavaScript默认为false。就像下面这样:

有的人可能会问为什么不判断是否为php、asp后缀呢?原因很简单,光一个php就有php3、php等格式了。而且只需要在服务端配置下。nihao这样的后缀都可以以php的方式解析,所以说我就使用了图片格式来进行判断。

当判断成功后,接下来就是return的事了,其实这里还需要一个判断,就是判断当前的form表单里的input[type]属性的值是否存在text、password、radio、checkbox其中之一,而且必须存在type=submit。不然还是不符合条件。总不能还写一个if,那也太麻烦了。这里我们就使用return来判断。因为filter函数只返回turn组成的数组,利用这个特性,我们就在return里判断。代码如下:

return $(index).find(":submit").length > 0 && ($(index).find(":text").length > 0 || $(index).find(":password").length || $(index).find(":radio").length > 0 || $(index).find(":checkbox").length > 0);

当前的表单必须存在submit,如果不存在则返回false,如果存在则判断后面的表达式是否为turn,因为&&是必须两个表达式都为turn时,才返回turn。也就是说($(index).find(":text").length > 0 || $(index).find(":password").length || $(index).find(":radio").length > 0 || $(index).find(":checkbox").length > 0)这里的表达式,必须有一个符合条件才可以。

OK,这个时候存在图片的判断已经写完了,那当前的form表单不存在图片怎么办呢?这个时候我们就不需要那么多的if判断图片格式了。我就直接在else里写上:

return $(index).find(":submit").length > 0 && ($(index).find(":text").length > 0 || $(index).find(":password").length || $(index).find(":radio").length > 0 || $(index).find(":checkbox").length > 0);

就可以搞定了。

现在我们来看下反馈是怎么样的:

这个时候可以清楚的看到,第三个form表单。也就是验证码的那么表单,已经被忽视了。

接下来就是判断如果当前页面符合上文这些条件的表单一个都没有,那就跳出这个函数体。代码如下:

if(tureForm.length <= 0){
    return false;
}

当tureForm一个数组都不存在时,则就跳出这个函数体(form_Xss),就不在向下运行代码了。

现在我们还要在判断当前表单的input是否存在name属性,如果不存在则跳出这个函数体,为什么要判断这个呢,因为没有name值的话,ajax无法构造请求,这样无法发送数据,更别谈检测了。代码如下:

tureForm = $(tureForm).filter(function(item,index){
    return (!!$(index).find(":input").attr("name"));
})
if(tureForm.length <= 0){
    return false;
}

filter这段代码完成的功能就是,把当前的form表单重新组合,把具有name属性的input标签组成新的form表单,把不存在name属性的标签给剔除掉。

下面的if是判断当前新的form标签里有没有input了,没有input的话,就跳出循环。

完整的代码如下:

tureForm = $("form").filter(function(item,index){
    formImg = $(index).find("img").attr("src");
    if(!!formImg){
        if(formImg.indexOf("?") != "-1"){
            formImg = formImg.slice(0,formImg.indexOf("?"));
        }
        formImg = formImg.substr(formImg.lastIndexOf("."),formImg.length);
        if(formImg == ".png" || formImg == ".jpg" || formImg == ".jpeg" || formImg == ".gif"){
            return $(index).find(":submit").length > 0 && ($(index).find(":text").length > 0 || $(index).find(":password").length || $(index).find(":radio").length > 0 || $(index).find(":checkbox").length > 0);
        }
    }else{
        return $(index).find(":submit").length > 0 && ($(index).find(":text").length > 0 || $(index).find(":password").length || $(index).find(":radio").length > 0 || $(index).find(":checkbox").length > 0);
    }
})
if(tureForm.length <= 0){
    return false;
}
tureForm = $(tureForm).filter(function(item,index){
        return (!!$(index).find(":input").attr("name"));
})
if(tureForm.length <= 0){
    return false;
}

0×05 发送数据

现在的tureForm包含了具有符合条件的form表单数据的数组,这里我们就可以使用for循环来依次拼凑&发送&反馈了。代码如下:

for(i = 0;i < tureForm.length;i++){
    /*tureForm[i]代表当前的form表单*/
}

接下来就是获取当前form表单的action发送地址和method发送模式了。

actionUrl = $(tureForm[i]).attr("action");
methodType = $(tureForm[i]).attr("method");

actionUrl代表了当前form表单的action字符串,methodType同理。

这里可能又问会问,如果没有action或者method怎么办呢,在说这个之前,我先科普下小知识,当form表单没有action属性时,默认是提交到本页面的,而没有method属性时,默认是以get的请求发送的。知道这些下面的代码就好理解了:

if(actionUrl == undefined || actionUrl == "#" || actionUrl == ""){
    actionUrl = href;
}
if(methodType == undefined || methodType == ""){
    methodType = "get";
}

判断是否为undefined是因为当form表单没有action或者method属性时会返回undefined。至于为什么要判断action是否为#,因为#代表的也是本页面。

当不存在action属性或者action为#、空时,action为本页面。method同理。

下面就是去掉当前form表单里的除submit之外所有的input个数:

tureInput = $(tureForm[i]).find("input:not(:submit)").length;

下面就是对这些input的拼凑。这里还需要一个for循环,最外层的for循环是获取当前的form表单,这里的for循环是获取当前form表单里的input标签。

for(j = 0;j < tureInput;j++){
    sendData += $(tureForm[i]).find("input:not(:submit)")[j].getAttribute("name") + "=" + onlyString + j + "&";
}

sendData是拼凑后的字符,至于为什么这里不用attr,而是用getAttribute这种原生态JavaScript,因为前面的[j]就已经把前面的jQuery对象转成原生态的JavaScript了,想要使用attr也可以,这样写:

$($(tureForm[i]).find("input:not(:submit)")[j]).getAttribute("name")

只是这样太浪费效率了,jQuery转JavaScript再转jQuery,不值得。

onlyString + j就是当前这个input的唯一标识符了。

当然for循环后肯定会多出一个&,现在我们来把他去掉:

sendDataUrl = sendData.substring(0,sendData.length-1);

因为sendData使用的+=,所以sendDate不能在全部变量里什么,于是我们在for开始的第一行写上var sendData = "";

就可以每一次循环就把sendDate清空。

现在我们来看看反馈:

下面就是利用ajax发送数据了:

$.ajax({
    url: actionUrl,
    type: methodType,
    dataType: 'text',
    data: sendDataUrl,
    async:false,
})

Url是action发送地址,type是method发送模式,data就是拼凑的数据。

async:false是以异步发送,防止for+ajax的bug。

当发送成功后,我们需要再在服务端反馈的数据里找到某个form标签里的某个input的唯一标识符。

发送成功的ajax函数是:

.done(function(data){
    /*data为发送成功后,服务端的反馈的数据*/
})

先var xss = "";,把存在XSS的数据,存放在里面。

因为这个时候,我们还在最外层的for循环里,所以我们可以使用tureInput(当前form表单除去submit之外的input个数)变量。

我们就拿这个来进行for循环。

for(j = 0;j < tureInput;j++){
    if(data.indexOf(onlyString + j) != "-1"){
        xss += j + 1 + "|";
    }
}

If判断当前form发送的数据里存不存在XSS。这里的onlyString + j和上面拼接的数据是一样的,不然无法判断,当data.indexOf(onlyString + j) != "-1"的结果为true时,说明存在XSS,这个时候我们在把存在XSS的数据,放到xss变量里。

至于为什么要+1,是因为tureInput的长度是从0开始的,如果不+1,那到时候在日志反馈的时候,就是第0个input存在XSS漏洞了。至于后面会多出一个|字符,下面再做操作。

然后if判断当前的form存不存在XSS漏洞,其实也就是判断xss变量是否为空。

if(xss == ""){
    return false;
}else{
    /*存在XSS时,要运行的代码*/
}

当不存在时,跳出本函数,注意这个时候的函数体不是form_Xss()了,而是.done(function(data){}这个函数体。切记。

当存在XSS时,先去掉最后面的|字符。

xss = xss.substring(0,xss.length-1);

然后就是回显了,我这里提供三个回显的代码:

一、alert("当前页面action为" + actionUrl + "的form表单第" + xss + "个input存在XSS漏洞"); //直接弹出,因为页面的form表单无法直观的看到哪个是第一个,哪个是第二个,所以,这里就使用action来做为标识符。就像下面这样:

二、$(tureForm[i]).find("input").eq(xss – 1).css("border"," 3px solid red");直接给存在input的标签外部画上css,看起来直观,但是页面就不怎么好看了,就像下面这样:

三、$("body").append("<img src='http://xss.cn/formXSS.html?host=$" + href + "&$xss=$" + xss + "&$url=$" +actionUrl + "&$rand=$" + Date.parse(new Date()) + "' style='display:none;'>");   //也是我推荐的方式,反馈的结果如下:

完整的代码如下:

for(i = 0;i < tureForm.length;i++){
    var sendData = "";
    actionUrl = $(tureForm[i]).attr("action");
    methodType = $(tureForm[i]).attr("method");
    if(actionUrl == undefined || actionUrl == "#" || actionUrl == ""){
        actionUrl = href;
    }
    if(methodType == undefined || methodType == "#"){
        methodType = "get";
    }
    tureInput = $(tureForm[i]).find("input:not(:submit)").length;
    for(j = 0;j < tureInput;j++){
        sendData += $(tureForm[i]).find("input:not(:submit)")[j].getAttribute("name") + "=" + onlyString + j + "&";
    }
    sendDataUrl = sendData.substring(0,sendData.length-1);
    $.ajax({
        url: actionUrl,
        type: methodType,
        dataType: 'text',
        data: sendDataUrl,
        async:false,
    })
    .done(function(data) {
        var xss = "";
        for(j = 0;j < tureInput;j++){
            if(data.indexOf(onlyString + j) != "-1"){
                xss += j + 1 + "|";
            }
        }
        if(xss == ""){
            return false;
        }else{
            xss = xss.substring(0,xss.length-1);
            // $(tureForm[i]).find("input").eq(xss - 1).css("border"," 3px solid red");
            // alert("当前页面action为" + actionUrl + "的form表单第" + xss + "个input存在XSS漏洞");
            $("body").append("<img src='http://xss.cn/formXSS.html?host=$" + href + "&$xss=$" + xss + "&$url=$" +actionUrl + "&$rand=$" + Date.parse(new Date()) + "' style='display:none;'>");
        }
    })
}

0×06 重写反馈

在上一节,我们看到第三种方法的反馈,现在就是重写这种反馈。我们这里就直接说代码了,日志环境的重新搭建,请移步FB文章《打造一个自动检测页面是否存在XSS的插件Ⅱ》的第0×01和0×02小节观看。

重新后的代码和直接比,是没有什么太大的变化的,就是添加了“默认隐藏”、“点击打开”、“提醒文字”、“把html移到JavaScript之外,JavaScript只负责数据处理”。

因为默认是隐藏,点击在打开,所以我们需要css代码。如下:

<style>
    .hide{
        display: none;
    }
    .show{
        display: inline-table !important;
    }
    small{
        color: #898FFF;
    }
</style>

大体的格式如下:

Script里就是处理数据的,和之前的是没什么太大变化。

这里因为要实现“默认隐藏”和“点击隐藏”,我们在body下面需要再新建一个script标签,代码如下:

<script>
    $(".panel-heading").next("table").addClass('hide');
    $(".panel-heading").click(function() {
        if($(this).next("table").attr("class") == "table hide"){
            $(this).next("table").removeClass('hide');
            $(this).next("table").addClass('show');
        }else{
            $(this).next("table").removeClass('show');
            $(this).next("table").addClass('hide');
        }
    });
</script>

完整的的代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>XSS反馈</title>
    <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.js"></script>
    <link rel="stylesheet" type="text/css"href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.css">
    <style>
        .hide{
            display: none;
        }
        .show{
            display: inline-table !important;
        }
        small{
            color: #898FFF;
        }
    </style>
</head>
<body>
<div class="panel panel-default">
    <div>网站URL参数存在XSS漏洞结果</div>
    <table>
        <thead>
            <tr>
                <th>序列</th>
                <th>网站域名</th>
                <th>存在漏洞参数</th>
                <th>完整的原URL</th>
            </tr>
        </thead>
        <tbody>
            <script>
                $.ajax({
                    url: '/logs/getXSS.log',
                    type: 'get',
                    dataType: 'text',
                })
                .done(function(data) {
                    var host = "";
                    var xss = "";
                    var url = "";
                    var htmlText = "";
                    data = data.split("\n");
                    if(data[data.length-1] == ""){
                        data.pop();
                    }
                    for(var i = 0;i < data.length;i++){
                        data[i] = data[i].substring(15);
                        data[i] = data[i].substring(0,data[i].length-11);
                    }
                    for(i = 0;i<data.length;i++){
                        data[i] = data[i].split("&$");
                        host += data[i][0].split("=$")[1] + " ";
                        xss += data[i][1].split("=$")[1] + " ";
                        url += data[i][2].split("=$")[1] + " ";
                    }
                    host = host.split(" ");
                    host.pop();
                    xss = xss.split(" ");
                    xss.pop();
                    url = url.split(" ");
                    url.pop();
                    for(i = 0;i < data.length;i++){
                        htmlText += "<tr><td>"+ (i+1) +"</td><td>" + host[i] + "</td><td>" + xss[i] + "</td><td>" + url[i] + "</td></tr>";
                    }
                    $($("tbody")[0]).append(htmlText);
                })
            </script>
        </tbody>
    </table>
</div>
<div class="panel panel-default">
    <div>网站Form表单存在XSS漏洞结果 <small>“存在漏洞参数”以 | 为分隔符,1代表第一个input,2代表第二个input。input的位置在action地址的Form表单里</small></div>
    <table>
        <thead>
            <tr>
                <th>序列</th>
                <th>网站URL</th>
                <th>存在漏洞参数</th>
                <th>Form表单的action地址</th>
            </tr>
        </thead>
        <tbody>
            <script>
                $.ajax({
                    url: '/logs/formXSS.log',
                    type: 'get',
                    dataType: 'text',
                })
                .done(function(data) {
                    var host = "";
                    var xss = "";
                    var url = "";
                    var htmlText = "";
                    data = data.split("\n");
                    if(data[data.length-1] == ""){
                        data.pop();
                    }
                    for(var i = 0;i < data.length;i++){
                        data[i] = data[i].substring(15);
                        data[i] = data[i].substring(0,data[i].length-11);
                    }
                    for(i = 0;i<data.length;i++){
                        data[i] = data[i].split("&$");
                        host += data[i][0].split("=$")[1] + " ";
                        xss += data[i][1].split("=$")[1] + " ";
                        url += data[i][2].split("=$")[1] + " ";
                    }
                    host = host.split(" ");
                    host.pop();
                    xss = xss.split(" ");
                    xss.pop();
                    url = url.split(" ");
                    url.pop();
                    for(i = 0;i < data.length;i++){
                        htmlText += "<tr><td>"+ (i+1) +"</td><td>" + host[i] + "</td><td>" + xss[i] + "</td><td>" + url[i] + "</td></tr>";
                    }
                    $($("tbody")[1]).append(htmlText);
                })
            </script>
        </tbody>
    </table>
</div>
<script>
    $(".panel-heading").next("table").addClass('hide');
    $(".panel-heading").click(function() {
        if($(this).next("table").attr("class") == "table hide"){
            $(this).next("table").removeClass('hide');
            $(this).next("table").addClass('show');
        }else{
            $(this).next("table").removeClass('show');
            $(this).next("table").addClass('hide');
        }
    });
</script>
</body>
</html>

现在的页面就是这样:

结语

之前有朋友和我说360也推出了XSS自动检测插件,我也下载安装看了。不能说谁的更好,只能说各有千秋,360的XSS检测插件主要是针对URL的参数进行fuuzing,灵活性比我写的好多了。但是反馈需要提升。同一个参数存在XSS的话,会出现好几个alert弹窗。360的更加趋向于灵活性。我这个更加的趋向于自动化操作。不过360倒是提醒了我平台的重要性,下面是chrome、Maxthon插件下载地址:

合计:http://pan.baidu.com/s/1c0375vU

Chrome:上传插件还要交费,所以我就没上传到chroem应用平台

Maxthon:http://extension.maxthon.cn/detail/index.php?view_id=2899

最后说下,后面会在这个插件的基础上添加“路径扫描”“任意文件读取”等功能。

*本文来自FreeBuf特约作者Black-Hole投稿,属FreeBuf黑客与极客(Freebuf.COM)独家发布,未经允许禁止转载。

这些评论亮了

  • 冰海 (4级) 我思故我在…… 回复
    楼主大赞,大清早的第一份礼物,太棒了!
    )7( 亮了
  • 夜尽天明 (6级) 千秋邈矣独留我,百战归来再读书 回复
    这个会存在误判么
    )7( 亮了
  • 冰海 (4级) 我思故我在…… 回复
    @ Black-Hole 调试时看到onlyString这个地方的问题了,已自行修改。
    Chrome浏览器加载此crx插件,需要重命名为rar/zip,解压后用开发者模式加载目录即可使用。
    楼主码字辛苦了^_^
    )7( 亮了
  • pat007 (3级) 回复
    学习了,不错!可以拿补天漏洞平台开涮吗 ~~
    )6( 亮了
  • Black-Hole (6级) FreeBuf专栏作者 回复
    @ 夜尽天明  很抱歉,因为唯一标识符的问题,请博主修改一下onlyString变量为"woainixss<script>alert(123)</script>"方可解决问题,直接下载chrome插件,改为zip,解压后,打开base.js修改onlyString变量。使用chrome浏览器自带封装插件功能,即可解决问题。这几天我会更新一下百度盘的插件,到时候会通知你。感谢支持
    )6( 亮了
发表评论

已有 14 条评论

取消
Loading...

特别推荐

推荐关注

填写个人信息

姓名
电话
邮箱
公司
行业
职位
css.php