前言
XSS(cross site scripting)即跨站脚本攻击,是最常见的web应用程序漏洞之一。
XSS是指攻击者在网页嵌入客户端脚本,通常使用的是JavaScript编写的恶意代码,当用户浏览网页时,恶意代码将在用户的浏览器上执行。
XSS属于前端漏洞,受害者是用户,但是网站的管理人员也是用户之一,也有可能被攻击者拿到管理员权限,作为跳板实施攻击。
本篇文章用于对XSS原理解析和对各种类型的XSS介绍。
XSS原理解析
XSS是在网页输入口插入用脚本语言(一般是JavaScript),如果服务端不对用户输入进行严格过滤且返回给客户端输出,那么就有可能造成跨站脚本漏洞。
JavaScript编写的脚本可以用来获取用户cookie,改变网页内容,URL跳转,那么存在XSS漏洞的网站,就可以盗取用户的cookie,黑掉页面,导航到恶意网站,而攻击者只需要在网页中注入JavaScript代码即可。
用本地搭建的网站环境测试:

get方式提交测试代码:
<script>alert(/xss/)</script>

利用post方式提交:

网页源代码为:
1 | <html> |
php代码为:
1 | <html> |
可以看到上述服务器对用户输入没有进行任何防护,直接在客户端上输出,就有了XSS漏洞。
JavaScript在HTML中不仅由上述方式加载脚本,还有:
<script>脚本语句</script><script type="text/javascript" src="js文件地址"></script><input type="button" value="点击" onclick="var a='test';alert(a)">
注意:
在2中JavaScript加载外部的代码文件可以是任意扩展名(无扩展名也可以),如:
<script type="text/javascript" src="http://www.example.com/x.jpg"></script>即使文件扩展名为jpg,但是只要文件中包含js代码就会被执行。
在3中以HTML事件处理器中写入js代码,这里不光有onclick还有更多类似onmouseover,onmouseout等多种事件,对事件的如何触发也有不同,如:
<button onclick="this.innerHTML=Date()">现在的时间是?</button>
XSS类型
XSS总共分为三类:
- 反射型XSS
- 存储型XSS
- DOM型XSS
反射型XSS
反射型XSS,也被称为非持久型XSS,是最容易出现的一种XSS。用户点击一个攻击者生成的具有js代码的URL,服务器没有对URL严格过滤返回给用户,用户的浏览器执行js代码,最终造成XSS漏洞。
服务器代码:
1 |
|
则攻击者可以生成具有js代码的URL:
http://www.example.com/xss.php?username=<script>XSS恶意代码</script>
用户的点击后,就会执行XSS恶意代码。
存储型XSS
存储型XSS又称为持久性XSS,是最危险的一种跨站脚本,具有更高的隐蔽性,危害性更大。
允许用户存储数据的web应用程序都有可能会出现存储型XSS漏洞,当攻击者提交一段XSS代码后,服务器将其保存在数据库中,在正常用户访问某个页面时,这段代码将会被程序读出来响应给浏览器,造成XSS攻击。
这里用DVWA的存储型XSS(LOW)示例:

模拟了一个网站的评论区,这里注入XSS代码:

最终注入成功,因为XSS代码保存到数据库中,所以用户每次登陆这个界面都会触发代码:

DOM型XSS
DOM型XSS是基于DOM文档对象模型的一种漏洞。严格地说,DOM型XSS其实算反射型XSS,区别在于DOM型XSS并不会和后台进行交互,是完完全全的Web前端安全问题,要做防御也只能在客户端上进行防御。
首先,客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它并不与服务端进行交互而是从客户端获得DOM中的数据(如从URL中获取数据)并在本地执行;其次,浏览器用户可以操纵DOM中的一些对象如URL、location等;因此,当攻击者可以控制一些DOM对象、输入一些恶意JS代码,而客户端的脚本并没有对用户输入内容进行有效的过滤就传入一些执行危险操纵的函数如eval等或直接输出到页面时,就会导致DOM型XSS漏洞的存在。
DOM
DOM(Document Object Model),文档对象模型,是HTML和XML文档的编程接口。
其中HTML DOM定义了所有HTML元素的对象和属性,以及访问它们的方法。换言之,HTML DOM是关于如何获取、修改、添加或删除HTML元素的标准。关于DOM树的操作方法之后会介绍。
DOM以树结构表达HTML文档。

下面是一个包含DOM型XSS漏洞的HTML页面:
1 | <html> |
上述HTML文档中的JavaScript代码会将URL中参数 ‘name=’ 内容截取下来,写入到DOM结构中,也就是HTML文档中,其功能的实现全都在前端JS中进行、未与后台进行任何交互。

测试payload:
http://www.example.com/domxss.html?name=<script>alert(1)</script>
虽然会用get方式提交name数据,但是实际实现是在前端的script代码中,也可以为了绕过后端服务器的检测,使用如下payload:
http://www.example.com/domxss.html#name=<script>alert(1)</script>
其中#号表示在URL中#后面的内容不会传到后端处理,只在前端使用,这样就可以隐蔽恶意代码不被后端检测出来。
