一.实验目的
本实验的目的是帮助学生了解跨站请求伪造(CSRF)攻击。CSRF 攻击涉及一个受害用户、一个受信任的网站和一个恶意网站。受害用户在访问恶意站点时,正在与受信任的网站保持活动会话。恶意网站将可信网站的HTTP 请求注入到受害者用户会话中,造成损害。
在本实验中,学生们将通过CSRF 攻击来攻击一个社交网络应用。这个开源的社交网络应用被称为Elgg,它已经被安装在我们的虚拟机中。Elgg 中有针对CSRF 的防御措施,但为了达到本实验的目的,我们已经将这些防御措施关闭。本实验覆盖以下主题:
1. 跨站请求伪造攻击
2. CSRF 对抗措施:秘密令牌(secret token)和同站cookie(same-site cookie)
3. HTTP GET 和POST 请求
4. JavaScript 和Ajax
二.实验步骤与结果
2.1 Task 1:观察HTTP 请求
在跨站请求伪造攻击中,我们需要伪造HTTP 请求。因此,我们需要知道一个合法的HTTP 请求是什么样子的,以及它使用什么参数等。为此,我们可以使用一个名为”HTTP Header Live” 的火狐浏览器插件。本任务的目标是熟悉这个工具。指导中给出了如何使用这个工具的说明(§ 5.1)。请使用这个工具在Elgg 中捕获一个HTTP GET 请求和一个HTTP POST 请求。请在你的报告中指出这些请求中所使用的参数。
在合法用户进行登录利用该工具进行抓取http报文,可以分别得到上图所示的POST报文和GET报文
在POST报文中,有elgg_token,elgg_ts,username和password等参数,而在GET报文中没有参数显示。
2.2 Task 2:使用GET 请求的CSRF 攻击
在这个任务中,我们需要Elgg 社交网络中的两个账户Alice 和Samy。Samy 想成为Alice 的朋友,但Alice 拒绝添加他为好友。Samy 决定使用CSRF 攻击来实现他的目标。他向Alice 发送了一个URL(通过电子邮件或在发布在Elgg 上)。Alice 对这个网址很好奇,点击了这个网址,这就把她带到了Samy 的网站 www.attacker32.com 。假设你是Samy,描述你如何构建网页的内容,以便当Alice 访问该网页时,Samy 能够被添加到Alice 的好友列表中(假设Alice 有一个活跃的Elgg 会话)
实现思路:
通过抓获合法添加好友过程中得到的报文,观察其中的参数结构,然后通过修改其参数,构建网页的内容
实现步骤:
首先登录到Samy的用户界面后,合法的把Alice添加为好友,在该过程中利用插件工具进行抓获http报文如下:
可以看到其url请求为 ”http://www.seed-server.com/action/friends/add?friend=56” 开头,该56为Alice的guid
因此我们想要让Alice添加Samy为好友的话,需要把friend后的参数修改为Samy的guid。而Samy的guid可以在合法登录到Samy的用户界面后,通过网页的源码得到,如下:
最后根据得到的gid构造img上所附带的链接,如下:
攻击实现如下:
在攻击页面中,点击链接后,刷新Alice的好友页面,就可以观察到Samy被成功添加为Alice的好友。
2.3 Task 3:使用POST 请求的CSRF 攻击
在把自己加入Alice 的朋友名单后,Samy 想进行更多的攻击。他想让Alice 在她的个人资料中写上”Samy is my Hero”,使得所有人都能够看到。当然,Alice 不喜欢Samy,更不用说把这个声明写进她的个人资料中。Samy 计划使用CSRF 攻击来实现这一目标,也就是这个Task 的目标。
实现思路:
同上一个任务中的方法,在合法用户修改个人资料的过程中,利用插件截获http报文后,根据报文中的参数进行修改攻击页面中的内容,即可实现攻击。
实现步骤:
首先在Samy的用户页面中,进行修改自己的个人资料,把个人描述修改为“Samy is my hero.”在提交过程中,利用插件进行捕获http报文,得到如下结果:
可以看到该链接的网址以及报文中的参数内容,然后根据得到的报文对攻击网页的源码进行修改,即修改网页文件中的field中的参数以及p.action的内容。
修改后,进入该攻击页面,即可成功修改Alice的个人资料如下:
问题回答:
问题1:如何获取Alice的guid?
答:在上一个任务中,通过Samy在自己的用户页面添加Alice为好友的过程中,截获http报文,即可得到Alice的guid。
问题2:如果Boby 想向任何访问他的恶意网页的人发动攻击。在这种情况下,他事先不知道谁在访问该网页。那么他还能发动CSRF 攻击来修改受害者的Elgg 资料吗?请解释原因。
答:不可以。因为在攻击过程中需要知道受害者的guid并且预先设置好,如果是未知用户访问的话是不能够及时构造的。
2.4 Task 4:开启Elgg 的防御措施
开启防御措施要打开防御措施,首先要进入Elgg 容器的/var/www/elgg/vendor/elgg/elgg/engine/classes/Elgg/Security 文件夹,从Csrf.php 中删除return 语句。你可以使用一个内置在容器中的简单编辑器,名为nano 。在做了修改之后再次重复之前的攻击,看看你的攻击是否会成功。请指出捕获的HTTP 请求中的秘密令牌,并解释为什么攻击者为什么不能在CSRF 攻击中发送这些秘密令牌;是什么阻止了他们从网页上发现秘密令牌?
实现步骤:
首先在容器中修改文件内容,讲return语句注释掉,如下图所示:
然后重新进行攻击,可以观察到如下结果:
可以发现两次攻击都无法成功,网页会报错”form is missing __token or __ts fields”
捕获的http请求中的token如下:
由于return注释掉后,会执行validate函数,提取出请求中的两个参数__token 和__ts,但是由于在此前构造请求时没有补充这两个参数,因而会报错,并且攻击会失败
2.5 Task 5:测试同站Cookie 方法
当访问该网站时,浏览器上会设置三个cookie,分别是:cookie-normal、cookie-lax 和cookie-strict。正如其名称所示,第一个cookie 只是一个普通的cookie,第二个和第三个cookie 是两种不同类型的同站cookie(Lax 和Strict)。我们设计了两组实验来观察当发送HTTP 请求时,哪些cookie 会被附加到服务器上。通常情况下,属于服务器的所有cookie 都将被附加到请求中,除了同站cookie。
请点击两个实验的链接。链接A 指向example32.com 上的一个页面,而链接B 则指向attacker32.com 上一个页面。两个页面都是相同的(除了背景颜色),并且它们都发送三种不同的请求到 www.example32.com/showcookies.php ,这个链接只是显示浏览器发送的cookies。通过观察显示的结果,你可以知道哪些cookie 会被浏览器发送。请完成以下要求:
• 请描述你所看到的情况,并解释为什么在某些情况下不发送一些cookie。
在同站请求的三种情况下,三个cookie都被发送
在跨站请求的情况下:
Sending Get Request (link):
Sending Get Request (form):
Sending Post Request (form):
通过观察,可以得知,在跨站请求中,strict值都会阻止浏览器发送cookie到目标站点,而lax值则只有在post请求中才会被阻止发送。解释如下:
查阅RFC文档中的samesite部分可以得到如下内容:
从中可以得知strict值将阻止浏览器在所有跨网站浏览上下文中将 cookie 发送到目标站点,即使遵循常规链接也是如此。而 Lax 值为希望在用户从外部链接到达后维护用户登录会话的网站提供了安全性和可用性之间的合理平衡,因此在get请求中会发送而在post请求中为了防御CSRF而不会被发送。
• 根据你的理解,请描述同站cookies 如何帮助服务器检测一个请求是跨站还是同站请求。
只需要检查该请求中的Strict值是否还在,即可知道该请求是跨站还是同站请求,因为在同站请求中,三个值都会保留而跨站请求中Strict值都不会被发送。
• 请描述你将如何使用同站cookie机制来帮助Elgg防御CSRF攻击。只需要描述思路,无需实现。
利用同站cookie和token一同使用,利用strit值进行检查是否为跨站请求。在服务端产生同步token,为用户的每一次会话请求都进行验证。并且token不应该用cookies进行传送,而是作为响应缓存的一部分,比如HTML或者JSON响应。