XSS的原理与分类
什么是XSS?
XSS全称(Cross Site Scripting)跨站脚本攻击,是最常见的Web应用程序安全漏洞之一,位于OWASP top 10 2013/2017年度分别为第三名和第七名,在最新的owasp top 10 2021中XSS被归入注入漏洞,排第三名。XSS是指攻击者在网页中嵌入客户端脚本,通常是JavaScript编写的危险代码,当用户使用浏览器浏览网页时,脚本就会在用户的浏览器上执行,从而达到攻击者的目的。
从上面中的一段话,可以得知,XSS属于客户端攻击,受害者最终是用户,但特别要注意的是网站管理人员也属于用户之一。这就意味着XSS可以进行“服务端”攻击,因为管理员要比普通用户的权限大得多,一般管理员都可以对网站进行文件管理,数据管理等操作,而攻击者一般也是靠管理员身份作为“跳板”进行实施攻击。
XSS攻击最终目的是在网页中嵌入客户端恶意脚本代码,最常用的攻击代码是javascript语言,但也会使用其它的脚本语言,例如:ActionScript、VBscript。而如今的互联网客户端脚本基本是基于Javascript,所以如果想要深入研究XSS,必须要精通Javascript。
XSS换句话说,JavaScript能做到什么效果,XSS的胃口就有多大。这完全不是危言耸听。javascript可以用来获取用户的cookie,弹出窗口,那么存在XSS漏洞的网站,XSS就可以用来盗取用户Cookie,废掉页面,导航到恶意网站!更高端的XSS代码完全可以进行监控你的键盘操作,模仿Windows注销界面,诱导你输入开机密码!而攻击者需要做的仅仅是向你的代码中注入Javascript代码!
XSS漏洞出现的原因
程序对输入和输出的控制不够严格,导致”精心构造“的脚本输入后,在输到前端时被浏览器当作有效代码解析执行从而产生危害。
XSS的危害
针对用户
- 窃取用户Cookies资料,从而获取用户隐私信息,或利用用户身份进一步对网站执行操作
- 劫持用户浏览器会话,将用户当前使用的SessionID信息发送至攻击者控制的网站或服务器中,从而执行任意操作。例如进行非法转账、强制发表日志、发送电子邮件等
- 网站钓鱼。在网页中通过JS脚本,生成虚假的页面,欺骗用户执行操作,而用户所有的输入内容都会被发送到攻击者的服务器上
- 网页挂马(水坑攻击)
- 有局限性的键盘记录
- 发广告刷流量
针对WEB服务
- 内网扫描
- 进行大量的客户端攻击,如DDoS攻击
- 结合其他漏洞,如CSRF漏洞,实施进一步作恶
- 传播跨站脚本蠕虫
XSS分类
反射型XSS
反射型跨站脚本也称非持久型跨站脚本、参数型跨站脚本。这种类型的跨站脚本是最常见,也是使用最广泛的一种,主要用于将恶意脚本附加到URL地址的参数中。
反射性XSS的利用一般是攻击者通过特定手法(比如利用电子邮件),诱使用户去访问一个含有恶意代码的URL,当受害者点击这些专门设计的链接的时候,恶意JavaScript代码会直接在受害者主机的浏览器执行。它的特点是只在用户点击时触发,而且只执行一次,非持久化,所以称为反射型跨站脚本。
反射型XSS的攻击流程图:

此类XSS通常出现在网站的搜索栏、用户登录入口等地方,常用来窃取Cookie或进行钓鱼欺骗。
反射型XSS的危害往往不如存储型XSS,因为恶意代码暴力在URL参数中,并且时刻要求用户单击方可触发,稍微有点安全意识的用户可以轻易看穿链接是不可信任的。如此一来反射型XSS的攻击成本要比存储型XSS高得多。
反射型XSS的URL可能被用户怀疑,但是可以通过短网址服务将之缩短,从而隐藏自己。
反射型XSS测试代码:
1 |
|
http://hackrock.com/mylabs/xss/xss1.php?name=<script>alert(1)</script>

可以看到执行了JavaScript中的代码
存储型XSS
存储型跨站脚本也称持久型跨站脚本,比反射型跨站脚本更具威胁性,并且可能影响到Web服务器自身的安全。
此类XSS不需要用户单击特定URL就能执行跨站脚本,攻击者事先将恶意的JavaScript代码上传或存储到漏洞服务器中,只要受害者浏览包含此恶意JavaScript代码的页面就会执行恶意代码。
存储型XSS的攻击流程图:

存储型XSS一般出现在网站的留言、评论、博客日志等交互处,恶意脚本常常被存储到客户端或者服务器的数据库中,当其他用户浏览该网页时,站点即从数据库中读取恶意用户存入的非法数据,然后显示在页面中,即在受害者主机上的浏览器执行恶意代码。
存储型XSS不需要用户去单击URL进行触发,所以它的危害比反射型XSS大,黑客可以利用它渗透网站、挂马、钓鱼……
更严重的是,利用此类XSS能够轻易写危害性更大的XSS蠕虫,跨站蠕虫是使用Ajax/JavaScript脚本语言编写的蠕虫病毒,能够在网站中实现病毒的几何数级传播,其感染速度和攻击效果都非常可怕。XSS蠕虫会直接影响到网站中的所有用户,也就是一个地方出现XSS漏洞,同站点下的所有用户都可能被攻击。可想而知XSS蠕虫对网站的打击是十分巨大的。
另外,存储型XSS的恶意代码并不止是存储在服务器的数据库中,凡是能够进行持久化XSS都可以称之为存储型XSS,例如存储在浏览器的Cookie文件、LocalStorage、IndexedDB等本地存储中。随着HTML5的广泛普及,这种存储方式也越来越流行。
存储型XSS测试代码:
1 |
|
这是一个非常简单的留言板程序

但是当我们再留言板中插入了一段XSS的payload

弹出提示框,成功执行了JavaScript代码

DOM型XSS
实际上,这种类型的XSS并非按照“数据是否保存在服务器端”来划分,DOM Based XSS从效果上来说也是反射型XSS。单独划分出来,是因为DOM Based XSS的形成原因比较特别,发现它的安全专家专门提出了这种类型的XSS。出于历史原因,也就把它单独作为一个分类了。
DOM-XSS不经过后端,而是通过DOM节点形成的XSS。
DOM型XSS在攻击中的优势:
避开waf
因为有些情况DOM-XSS的Payload,可以通过
location.hash,即设置为锚部分从#之后的部分,既能让JS读取到该参数,又不让该参数传入到服务器,从而避免waf检测。location.search也类似,它可以把部分参数放在?之后的部分。长度不限
这个很重要,关键时候,长度不够,可不是什么小药丸就解决的。
隐蔽性强
攻击代码可以具有隐蔽性,持久性。例如使用Cookie和localStorage作为攻击点的DOM-XSS,非常难以察觉,且持续的时间长。
DOM型XSS测试代码:
1 |
|
点击write按钮后,会在当前页面插入一个超链接,其地址为文本框的内容:

在这里,write按钮的onclick事件调用了test()函数。而在test()函数中,修改了页面中的DOM节点,通过innerHTML把一段用户数据当做HTML写入到了页面中,这就造成了DOM-XSS。
构造如下数据:
1 | ' onclick=alert(1) // |
输入后,页面代码就变成了:
1 | <a href='' onclick=alert(1) //' >testLink</a> |
首先用一个单引号闭合掉href的第一个单引号,然后插入一个onclick事件,最后再用注释符“//”注释掉第二个单引号。
点击这个新生成的链接,脚本被执行:

实际上,这里还有另一种利用方式——除了构造一个新事件外,还可以选择闭合掉<a>标签,并插入一个新的HTML标签。尝试如下输入:
1 | '><img src=# onerror=alert(1) /><' |
页面代码变成了:
1 | <a href=''><img src=# onerror=alert(1) /><'' >testLink</a> |
XSS漏洞挖掘场景
黑盒测试
尽可能找到一切用户可控并且能够输出在页面代码中的地方,比如下面这些:
- URL的每一个参数
- URL本身
- 表单
- 搜索框
常见业务场景
- 重灾区:评论区、留言区、个人信息、订单信息等
- 针对型:站内信、网页即时通讯、私信、意见反馈
- 存在风险:搜索框、当前目录、图片属性等
白盒测试(代码审计)
关于XSS的代码审计主要就是从接收参数的地方和一些关键词入手。
PHP中常见的接收参数的方式有 $_GET、$_POST、$_REQUEST 等等,可以搜索所有接收参数的地方。然后对接收到的数据进行跟踪,看看有没有输出到页面中,然后看输出到页面中的数据是否进行了过滤和html编码等处理。
也可以搜索类似echo这样的输出语句,跟踪输出的变量是从哪里来的,我们是否能控制,如果从数据库中取的,是否能控制存到数据库中的数据,存到数据库之前有没有进行过滤等等。
大多数程序会对接收参数封装在公共文件的函数中统一调用,我们就需要审计这些公共函数看有没有过滤,能否绕过等等。
同理审计DOM型注入可以搜索一些js操作DOM元素的关键词进行审计。
参考资料
- 邱永华 著《XSS跨站脚本攻击剖析与防御》
- XSS(跨站脚本攻击)详解 - 墨鱼菜鸡 - 博客园 (cnblogs.com)
- OWASP Top 10:2021