CSRF总结

CSRF介绍

跨站请求伪造(Cross-site request forgery,简称CSRF),一种常见的web安全漏洞,攻击者利用受害者身份发起了HTTP请求,导致受害者在不知情的情况下进行了业务操作;它允许攻击者部分规避同源策略,该策略旨在防止不同网站相互干扰,并且由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去执行,简单来说就是你点击我构造的恶意链接,我就可以以你的名义去发起一个http请求。常见的漏洞利用场景:修改资料、提交订单、发布留言或评论等,并且在Web应用中,用户登录后执行的操作中有些处理一旦完成就无法撤销,比如用户使用信用卡支付、从用户的银行账号转账、发送邮件、更改密码或邮箱地址等都成为了CSRF的典型攻击案例

CSRF主要的攻击形式

① GET类型的CSRF

这类攻击非常简单,只需要构造一个HTTP请求,即可完成攻击

② POST类型的CSRF
这种类型的 CSRF 利用起来通常使用的是一个自动提交的表单,访问问该页面后,表单会自动提交,相当于模拟用户完成了一次 POST 操作。可见这种类型的 CSRF 与第一种一样,都是模拟请求,所以后端接口也不能将安全寄托在仅允许 POST 请求上

③ 链接类型的 CSRF
链接类型的CSRF并不常见,比起其他两种用户打开页面就中招的情况,这种类型需要用户点击链接才会触发,但本质上与前两种一样。这种类型通常是在论坛发布的图片中嵌入恶意链接,或者以广告的形式诱导用户中招,攻击者通常会以比较夸张的词语诱骗用户点击,例如:<a href=” taget=”_blank”> 由于之前用户登录了信任的网站A,并且保存登录状态,只要用户主动访问这个页面,则表示攻击成功

CSRF漏洞原理

CSRF漏洞产生的原因

(1)http协议使用session在服务端保存用户的个人信息,客户端浏览器用cookie标识用户身份;

(2)cookie的认证只能确保是某个用户发送的请求,但是不能保证这个请求是否是”用户自愿的行为”.

(3)这时,用户登录了某个web站点,同时点击了包含CSRF恶意代码的URL,就会触发CSRF

漏洞利用的条件

(1)用户必须登录A网站,生成了cookie

(2)登录的同时访问了恶意URL(包含CSRF恶意代码的URL).

原理图

为了方便理解,可以看一下我下面做的这个流程图

例如,假设应用程序包含一个允许用户更改其帐户上的电子邮件地址的功能。当用户执行此操作时,他们会发出如下一个 HTTP 请求:

POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
Cookie: session=yvthwsztyeQkAPzeQ5gHgTvlyxHfsAfE

email=wiener@normal-user.com

这满足了CSRF所需的条件:
1、攻击者通常能够触发密码重置并完全控制用户的帐户
2、应用程序使用会话 cookie 来识别发出请求的用户
3、攻击者可以轻松执行、修改操作所需的请求参数的值

具备这些条件后,攻击者就可以构建包含以下 HTML 的网页:

1
2
3
4
5
6
7
8
9
10
<html>
<body>
<form action="https://vulnerable-website.com/email/change" method="POST">
<input type="hidden" name="email" value="pwned@evil-user.net" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>

如果受害者用户访问攻击者的网页,将会发生以下情况:

攻击者的页面将触发对易受攻击的网站的 HTTP 请求。
如果用户登录到易受攻击的网站,他们的浏览器将自动在请求中包含其会话 cookie
并且该网站将以正常方式处理该请求,视为由受害用户正常发出,却成功的更改了电子邮件地址
SUCCCESS!

参考文章:
https://www.freebuf.com/articles/web/247866.html
https://developer.aliyun.com/article/1207187
https://www.cnblogs.com/jingdongkeji/p/17799878.html

CSRF漏洞常见利用方式

下面我将用burpsuite官方靶场环境来做演示

无防御措施的CSRF漏洞

首先使用提供的账号密码登录实验室 wiener:peter

可以看到此时默认邮箱是 wiener@normal-user.net ,我们先随便模拟修改邮箱账号修改一个并抓个包

我们可以看到,数据包中只提交了一个修改后的邮箱数据,这里我们可以直接使用 burp 自带的功能来生成 POC,把邮箱修改成我们想要的攻击效果,也就是只需要修改 value 中的值就可以了

然后将生成的攻击链接 copy 一下,然后在同一个浏览器打开,来模拟受害者点击我们传播的 url 即可,此时可以看到邮箱修改成功,则表示攻击成功

有防护的CSRF漏洞(常见绕过)

未限制请求方法

还是刚才修改邮箱场景的靶场环境,首先我们先抓包看看数据包,分析一下修改邮箱怎么实现的

这里我们可以看到是存在一个 CSRF token 的,我们删了它看看是否会走校验

很遗憾,看来这个点还是有用的,尝试修改请求方法,看看这里我们能不能用 get 请求来修改邮箱呢

说明修改请求方法是成功的,可以绕过,我们继续删除后面的csrf参数,处理逻辑有没有变化,删除后发现也是可以成功修改的,这就说明当我们的请求方式改变之后,这个csrf参数的校验就失效了,于是我们就可以制作poc生成恶意攻击链接,并诱导受害者点击

未校验参数是否存在

这种漏洞出现的原因就是没有校验参数的完整性。通过观察数据包,如果修改关键参数并且不做校验,直接制作poc生成恶意攻击链接即可,这里就不赘述了

使用公共的CSRF token池

这种情况是由于这个应用没有将一个用户的 session 和他的 CSRF token 进行绑定,而是做了一个公共的CSRF token池,只要是这个池里的 token,都是有效的,绕过的思路那就是直接自己登录上去获取到一个 token 即可绕过

这一次需要两个账号 wiener 和 carlos 来进行演示
首先登陆 wiener 并观察数据包,请求包还是一样的,但是发现通过用上面的方式已经绕不过去了。这里我们先记录一下wiener的token值,然后登出 wiener 登录 carlos 在修改邮箱的时候替换 CSRF 的值,发现修改成功,成功绕过

这就说明,用户每次修改邮箱的时候需要一个服务器下发的一次性 CSRF token,但这个 token 并没有与 session 绑定,而是从公共token池中提取的,那么我们就可以通过自己的账号来获取一个有效的 CSRF token 来绕过这个校验机制,只不过每次有用户上钩之后我们需要刷新这个 token 值

这种情况下想要利用还需要有 CRLF 漏洞来配合,或者有其他的可以注入 cookie 的漏洞,使得你可以控制 cookie 的数据进而控制 csrf token 的数据

这次可以看到应该是走了双层验证,那么我们就需要一个地方来想办法注入 set-cookie,通过测试这里的搜索框存在 CRLF 漏洞,payload:%0d%0aSet-Cookie:%20csrf=123456%3b%20SameSite=None

那么我们就可以在自己的上构造一个响应,让它去请求刚才存在CRLF漏洞上的资源,然后发起一个请求来实现 CRLF 注入,之后再发送请求去修改邮箱就可以,首先还是用burpsuite先生成一个csrf的poc,然后对其修改:利用 img 标签去请求 web-security-academy.net(存在CRLF漏洞的完整URL)上的一个不存在的图片,当它发送这个请求的时候, web-security-academy.net 的 cookie 中的 csrf 键将被设置为 csrf=123456,当请求失败的时候,就会提交我们的 CSRF 代码来修改邮箱

1
2
3
4
5
6
7
8
9
10
11
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form action="https://0a7c00ee0362ba6884d4dc8700fe006e.web-security-academy.net/my-account/change-email" method="POST">
<input type="hidden" name="email" value="111&#64;normal&#45;user&#46;net" />
<input type="hidden" name="csrf" value="123456" />
<input type="submit" value="Submit request" />
</form>
<img src="https://0a7c00ee0362ba6884d4dc8700fe006e.web-security-academy.net/?search=test%0d%0aSet-Cookie:%20csrf=123456%3b%20SameSite=None" onerror="document.forms[0].submit();"/>
</body>
</html>

删除 referer 头

这次我们可以看到数据包中如果成功修改的话会自动跳转,同时请求包里有 referer 头,通常这种情况存在于开发人员在写代码的时候没有考虑到 referer 头不存在的情况下的处理逻辑,导致绕过了 referer 校验。但由于 referer 头是浏览器自动添加的请求头,所以通过上面的方式去要求 referer 头等于某个特定的值来绕过 referer 校验是不可行的,那我们看看把他改一下会是什么响应

这里报错是无效的 referer,那我们看看删了它会有什么响应

可以看到是成功的,那么下一步就是如何在 POC 里让它不发送 referer 头了,这就需要借助 meta 标签了(meta 标签用于提供关于 HTML 文档的元数据信息,也可以用来控制客户端发起请求的时候是否携带某个请求头),这里就是通过 meta 标签,来控制客户端发起请求不含 referer(no-referer),payload如下

CSRF防范措施

1、验证 HTTP Referer 字段
2、在请求地址中添加 token 并验证
3、在 HTTP 头中自定义属性并验证
4、浏览器端启用 SameSite cookie


CSRF总结
http://example.com/2024/02/06/CSRF总结/
作者
liuty
发布于
2024年2月6日
许可协议