一、XSS攻击简介
XSS(Cross Site Script),为了与CSS(层叠样式表)区别而命名。通常是指黑客通过“HTML注入”篡改网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击。
二、XSS攻击类型
首先将XSS分为三大类:
1)反射型
2)存储型
3)Dom Based XSS
三、XSS不同类型的攻击原理
1)反射型XSS,其特点是非持久型,一次性,不与数据库打交道。经常存在于需要用户输入数据的页面上,攻击者一般利用XSS Payload 嵌入其中链接中,通过散布链接,引用一些用户点击,从而获取用户的cookie,或窃取用户个人信息,对个人账户转账等恶意操作。
2)存储型XSS,其特点是持久性,非一次性,通过将用户输入的数据永久地“存储”在服务器端,当用户进行登陆时,或者使用url请求时,网站后台数据将自动执行XSS代码,导致用户身份认证丢失或其他重要信息丢失。
3)通过修改页面的DOM节点形成的XSS,一般叫做DOM Based XSS.
四 DVWA靶机上的应用
4.1 反射型XSS的利用与防范
1)高风险漏洞

header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Feedback for end user
    $html .= '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?> 

由于系统把用户的输入直接作为变量直接通过服务器发送html响应给客户端,浏览器解析后直接输出。并且未对用户的输入做任何过滤操作,导致黑客可以在html嵌入自己JS代码,当用户进行点击的时候,攻击便开始生效,于是乎写dvwa的大佬们,开始出下一道题,请你来解决,当对script标签进行替换掉时,便形成如下代码。
2)中风险漏洞

header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
    $name = str_replace( '<script>', '', $_GET[ 'name' ] );
    // Feedback for end user
    $html .= "<pre>Hello ${name}</pre>";
}
?>

对用户嵌入script进行替换,但是通过我们查找str_replace()函数,对大小写敏感。于是我们可以利用
Script进行替换,触发XSS攻击,或者sc script ript在script里嵌入script导致str_replace失效,也可以导致XSS漏洞触发,但是佬们并不局限于此,于是乎又修改后端代码。
3)低风险漏洞

<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
    // Feedback for end user
    $html .= "<pre>Hello ${name}</pre>";
}
?>

此时将使用更加严格的替换,我们并无法对script进行简单大小写,截断进行preg_replace()绕过,于是乎我们想到替换标签, 把script 改为对img的标签进行xss触发,实现成功绕过。
但是佬们也采取如下办法
4)无风险代码

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    // Get input
    $name = htmlspecialchars( $_GET[ 'name' ] );
    // Feedback for end user
    $html .= "<pre>Hello ${name}</pre>";
}
// Generate Anti-CSRF token
generateSessionToken();
?>

对输入name进行过滤采用严格的htmlspecialchars()函数,将“&”、“<”、">"、“ ‘ ”、“ " "等预定义符,转变为html实体,导致无法无法嵌入,这一点用于输出检查。另外的防范XSS的cookie劫持,可以给cookie加上HttpOnly,其他的防范措施,待以后更加深入了解后补上。而上述token一般是采取防范csrf时使用。
4.2 存储型XSS的利用与防范
佬们在为了让小白菜进一步快速掌握存储型XSS,于是乎又提出如下挑战,
图片说明
在页面有name输入框和消息输入框,当我查看后端代码可以看到,只截取重要部分

    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );
    $message = stripslashes( $message );
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";

我们发现,后台进行处理的时候,仅仅只时删除了message中的反斜杠,并未对用户的数据做其他操作,并且,每次打开页面的时候,该后台代码均会在guestbook表中执行查询操作,所以我们只需要嵌入XSS Payload即实现攻击。但佬们不可能轻易就放过小白菜,进而提升难度,进行如下防范,

    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );
    $message = strip_tags( addslashes( $message ) );
    $message = htmlspecialchars( $message );
    $name = str_replace( '<script>', '', $name );

佬们在message进行输出过滤,并且Name对script进行替换,我们想要绕过输出检测,于是乎由反射型XSS入手,发现只能通过Name框入手,message框是安全的。但是经过测试我们发现Name对输入进行限制,使用script根本写不完,于是乎我们利用工具burpsuite进行截断,然后进行构造请求,在返给浏览器,实现绕过name字符限制
图片说明
进而完成攻击
图片说明
然而佬们不满足于此,进而下一道难题。同样地在name处进而name=preg_replace()函数进行模式匹配,同样利用burpsuite继续头改包绕过,进行完成注入,注入同XSS反射,实现绕过。这里就不再进行叙述。
4.2 DOM Based XSS的利用与防范
当小白菜遇到DOM Based XSS时,显得手足失措,由于佬们不再平台发布任务,要求小白菜自己进行学习。小白菜由于无法上手,于是便自己“偷”他人成果来学习。某天发现吴佬给出如下代码

 <script>
function test(){
   var str = document.getElement.ById("text").value;
  document.getElementId("t")/innerHTML = "<a href='"+str+"' >testLink</a>";
}
</script>
<div id="t" ></div>
<input type="text" id="text" value"" />
<input type="button" id="s" value="write" onclick="test()" />

图片说明
细心小白菜发现,在页面插入一个write按钮,当用户进行点击时,将会执行test()函数,而在test()函数里边就在当前页面插入一个超链接,地址就是文本框的内容。而我们可以在文本输入任意我们想要执行XSS Payload,导致漏洞执行。

    可以构造' onclick=alert(/xss/) //输入后形成,<a href='' onclick=alert(/xss/)//'>testLink</a>

前一个单引号是为了屏蔽href的第一个单引号,插入一个onclick事件,最后再利用注释符"//"注释掉第二个单引号。这里小白菜嘿嘿直笑,只要诱导有人点击这个链接,就可以执行小白菜做的不可告人的秘密。但是并没有完毕,除了构造一个新的事件外,小白菜又从吴佬那里学习了一种新技能,

闭合<a>标签,并插入一个新的HTML标签,
'><img src=# onerror=alert(/xss/) /><'
页面代码变成了 <a href=''><img src=# onerror=alert(/xss/) /><'' >testLink</a>

从而导致脚本被执行。小白菜学到这里,于是有了一个疑问:DOM Based XSS 在什么情况下,会由于由于用户改变DOM节点从而导致漏洞的形成呢?
带着这个疑问,求教吴佬。吴佬给出一系列由于JavaScripts输出到HTML中的函数,包括如下

document.write()
document.writeln()
xxx.innerHTML=
xxx.outerHTML=
innerHTML.replace
document.attachEvent()
window.attachEvent()
document.location.repalce()
document.location.assign()
等

而吴佬告诉小白菜,你需要重点关注的这些函数的参数是否有用户进行控制。另外还有一些DOM Based XSS的输入点,也需要重点关注一下。

页面中所有的inputs框
window.location(href、hash等)
window.name
document.referrer
document.cookie
localstorage
XMLHttpRequest返回的数据

搞清楚原因的小白菜,跟着吴佬知道了,从JavaScript输出到HTML页面上,相当于依次XSS输出的过程,需要根据不同语境使用不同的编码函数,当变量输出到script标签里时,应该执行一个JavaScriptEncode;其次,在document.write输出到HTML页面时,要分具体情况看待;如果是输出到事件或者脚本,则要再做依次JavaScriptEncode;如果是输出到HTML内容或者属性,则要做依次HTMLEncode。
看到这里,佬们微微一笑。就此作罢。小白菜也开开心心睡上了一觉,等待更加艰巨的任务。