利用CSRF触发XSS攻击:隐藏的POST漏洞利用技术

本文详细介绍了如何通过跨站请求伪造(CSRF)技术利用基于POST方法的反射型XSS漏洞,包含攻击代码示例、隐藏技巧及防御措施,帮助开发者理解组合攻击的潜在风险。

XSS Through CSRF

2016年4月18日 星期一

首先要说明的是,我并不认为这种技术是新颖或独创的,也可能早已被他人使用多年。但由于最近频繁使用该技术,我认为值得写一篇博客来介绍它。

看看这段PHP代码片段:

1
2
3
4
5
6
7
8
9
<?php
if ($_SERVER['REQUEST_METHOD'] == "POST") {
    print "Welcome: " . $_POST['name'];
}
?>
<form method="POST" action="welcome.php">
    Name: <input type="text" name="name" /><br />
    <input type="submit" value="Submit" />
</form>

如果你不了解PHP,这里简单说明:在GET请求时显示表单要求用户输入姓名,在POST请求时直接显示输入的姓名且未进行任何过滤。这显然存在非常基础的反射型XSS漏洞,输入以下姓名将会触发一个警告框:

1
<script>alert(1)</script>

虽然非常基础,但许多开发者和用户会问:“如何让JavaScript代码进入其中?“如果反射是通过查询字符串参数实现的,我们可以轻松将其包含在URL中让受害者点击链接,但通过POST参数实现则稍微困难。

我们或许可以通过一些巧妙的社会工程学手段,告诉用户输入"特殊"代码可以获得购物折扣或查看其他用户的邮箱,但这增加了额外的步骤,也增加了潜在失败或被检测的风险。这时跨站请求伪造(CSRF)就派上了用场…

如果你了解跨站请求伪造(CSRF),就会发现该表单没有CSRF保护,这正是我们用来触发XSS的突破口。

以下是典型的CSRF利用脚本,它包含一个带有name字段的表单(与原始表单相同),但这次在value字段中放置了XSS代码。JavaScript在表单渲染后自动触发,将表单提交到易受攻击的页面。

1
2
3
4
5
6
<form method="POST" action="welcome.php">
    <input type="hidden" name="name" value="<script>alert(1)</script>" /><br />
</form>
<script>
    document.forms[0].submit();
</script>

如果该页面托管在攻击者控制的网站上,他们只需要诱使受害者访问该页面。一旦页面加载,表单就会自动提交并触发XSS。这比试图说服受害者自己输入利用代码要容易得多。

一个潜在的问题是受害者最终会停留在易受攻击的页面上,可能会发现异常情况。可以通过制造 pretext 让用户预期这种情况,但如果不可行,则需要一些混淆技术,这时iframe就派上了用场。该页面包含一些吸引受害者的文本,同时嵌入一个包含CSRF攻击页面的iframe。

1
2
<p>这是一个非常有趣的页面,充满了可爱猫咪的图片。</p>
<iframe style="opacity: 0.4;width: 200px;height: 200px" src="welcome_csrf.php" />

在实际攻击中,高度和宽度会设置为1px,不透明度为0,从而有效隐藏iframe。

就这样,我们通过CSRF和简单的框架技术相结合,提供了一种安静利用基于POST的反射型XSS的简单方法,如果需要的话,甚至可以在受害者毫无察觉的情况下完成攻击。

防御措施

有很多关于防范XSS的指南,主要包括在使用前对所有用户输入进行编码,以及在更现代的指南中启用内容安全策略(CSP)来阻止内联脚本。

为了防御这两种攻击方式的组合,还需要两个额外的简单防御措施。首先是防止原始网站被框架化,这可以通过X-Frame-Options头部实现。关于这方面的详细说明,可以参考OWASP指南。其次是添加CSRF保护,同样,OWASP有关于CSRF及其防御措施的很好介绍。

结论

本文的主要目的是说明基于POST的XSS不应因为难以利用而被忽视,同时也希望它能帮助你理解组合攻击如何使攻击更加有效。与我交谈过的相当多人都认为CSRF不是真正的问题,但正如多次所示,将足够多的看似低级别风险组合在一起,可能会产生远超各部分总和的效果。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计