XSS是Web安全中的常见漏洞,也是各位安全从业者刚入门时就会学习的漏洞。但从入门直到入行,还会有人对XSS漏洞一知半解,或者说对于其深入知识知之甚少。本篇文章将会涵盖绝大部分XSS漏洞的专业知识,从漏洞的基础开始,在自动化、绕过、利用手段、防御姿势等多个方面进行工业级的深入探讨。
一图胜千言,下图涵盖了本篇文章包涵的所有知识点:

图片说明

一、基础知识

从基础讲起,让我们回顾一下XSS的基础知识。XSS是一种触发点在前端的漏洞,它的一切都围绕着html、css与javascript展开。有人说XSS实际上是一种html的注入,其实这不全对,XSS也可能是javascript的注入,这一点会在后面的bypass阶段提现的淋漓尽致。当然,不论触发方式是什么,XSS的最终目的都是在受害者浏览器上执行任意javascript代码。
XSS可以简单的分为持久型XSS和非持久型XSS,但如果从漏洞成因和特点来看,可以单独列出四类:反射型XSS、存储型XSS、DOM型XSS以及富文本XSS。

1.1 反射型XSS

安全圈前两年有一句很火的话:『反射型XSS,忽略!』这句话的来源于当向各大厂商提交反射型XSS漏洞时,往往会因为漏洞危害过低而忽略。
这是因为反射型XSS是一种被动式的攻击:黑客将恶意代码写在url中,诱骗用户点击,从而触发漏洞。这种攻击充满了不确定性,加上恶意代码就明晃晃的暴露在url中,会引起人的警惕性,导致攻击成本提高。

反射型XSS的攻击原理图如上图所示,恶意代码<svg onload=alert(1)>作为请求中某个字段的值提交到后端后,由于后端未经安全处理,导致返回的html中携带了完整的<svg onload=alert(1)>,从而引发XSS弹框。
当然,上述只是很常见的Get请求的反射型XSS,近两年Post请求的反射型XSS逐渐多了起来。

其根本原理如上图所示,漏洞出发的原理是相同的,关键在于如何携带恶意代码发起Post请求。Post XSS结合CSRF漏洞很好的解决了这一问题:诱骗让用户点击某个恶意链接,通过CSRF漏洞发起一个Post请求,请求中带有恶意代码<svg onload=alert(1)>,由于后端未经安全处理,导致返回的html中携带了完整的<svg onload=alert(1)>,从而引发XSS弹框。
Post XSS击中的是开发者的盲点,可能一些开发者仅重视在Get请求处防御XSS漏洞,这一点是在漏洞挖掘过程中可以加以关注的。

1.2 存储型XSS

存储型XSS相对来说危害会更大,一般的厂商会给存储型XSS中危的评级,这是因为存储型XSS攻击较隐蔽,无需点击特制的恶意链接,当用户正常浏览时即可触发,如经典场景留言板:在留言板中插入一条带有恶意代码的留言,这样所有访问此留言板的人都会触发恶意代码。
存储型XSS在代码中并非一步到位,首先,恶意代码会被存入数据库中,当用户浏览时,将恶意代码从数据库中取出放入html中,从而引发XSS漏洞。攻击原理图如下所示:

这本质上是信任边界不清晰所导致的漏洞:用户输入存入数据库时,确保其不会产生SQL注入漏洞;认为从数据库中取出的数据是安全的,不进行任何处理直接输出到前端。两个步骤分开看似都是没问题的,然而合到一起就会产生漏洞。其实,数据库中的数据和用户输入都是处于信任边界之外的,需要进行安全处理。

1.3 DOM型XSS

『DOM型XSS与反射型XSS有什么不同?』这是在面试中经常会问到的一个问题。
DOM型XSS的特征和危害与反射型XSS是完全相同的,唯一的区别是:反射型XSS的值先请求到后端,后端未经处理又输出到前端;DOM型XSS的值不会请求到后端,是通过纯前端的javscript代码触发的。
比如一个搜索的场景,下图中『搜索结果如下 "恶意代码"』中的『恶意代码』是直接由javascript从地址栏中取值并赋予的,概念代码如下: