一篇文章学会csrf

admin 2024年1月23日12:06:32评论13 views字数 7623阅读25分24秒阅读模式

本篇文章我们将详细的介绍一下CSRF的相关知识,包括原理、分类、攻击手法、修复方法等。

注意测试尽量在测试环境进行,生产环境最好知道自己该干什么不该干什么!!!

注意测试尽量在测试环境进行,生产环境最好知道自己该干什么不该干什么!!!

注意测试尽量在测试环境进行,生产环境最好知道自己该干什么不该干什么!!!

什么是CSRF

跨站请求伪造 (Cross-site request forgery) 就是攻击者通过一定的手段使用户的浏览器去访问用户之前登录过并且令牌没有失效的网站,并执行他们本来不打算执行的操作。

比如一个网站存在 CSRF,那么攻击者通过 payload 可能会让用户在不经意间完成 修改账号绑定的邮箱、修改账号密码、转账 等等,通过这些操作攻击者就能完全控制受害者的账号。而如果受害者是系统管理员呢?那危害可能更大。

前提条件

  1. 这个网站上有值得你去攻击的功能。比如上面提到的修改邮箱、密码、转账、手机号 等,再不济也得有个增删改的功能吧,如果这个网站只是一个查看数据的地方,那你发起 CSRF 也没什么用,因为你拿不到对方查看的数据。

  2. 基于 cookie 的会话处理。这个网站对于客户端发起请求只通过 cookie 进行用户验证,没有其他的会话跟踪和用户验证机制。

  3. 没有不可预测的参数。比如 在修改密码的时候需要输入验证码或者原密码,这两个参数攻击者既不知道,也猜不到,那这个功能就不会被 CSRF 成功攻击

测试方法

对于 CSRF 的测试方法其实很简单

  1. 打开burp

  2. 找到你要测试的那个请求

  3. 右键 -> engagement tools -> Generate CSRF PoC

  • 一篇文章学会csrf

4.视情况改改 POC

5.点击 Test in browser -> copy

  • 一篇文章学会csrf

6.打开浏览器,粘贴刚才复制的 URL 到浏览器导航栏

7.回车之后如果执行成功那就是有 CSRF 漏洞

8.失败的话就看看报错是什么引起的来判断是POC的问题还是不存在 CSRF 漏洞,这个就需要具体情况具体分析了

利用方法

CSRF 的传播和反射型XSS的利用方式基本上是一样的:

  1. 攻击者把恶意代码放在其自己控制的网站上,诱导受害者访问这个网站

  2. 通过邮件、短信、社交软件进行传播

  3. 放在存在该漏洞的网站上,等待有缘人,比如评论区

CSRF 和 XSS 的区别

  1. XSS 允许攻击者在受害者的浏览器上执行 js 代码;而 CSRF 不行

  2. XSS 通过窃取受害者的 cookie 来实现账号接管,如果目标站点使用了 httponly 这就行不通了;CSRF 通过浏览器发起请求,自动携带受害者的cookie信息,即使有 httponly 也不影响 CSRF 攻击的实现

  3. XSS 的危害更大。攻击者如果成功实现了 XSS 攻击,那通常意味着他可以使用受害者在这个网站的所有功能,而 CSRF 只限于特定的存在漏洞的功能

  4. CSRF 无法让攻击者获取到服务器返回的数据,由于请求是由受害者的浏览器发起的,那么服务器的响应最后还是给到了受害者那里,攻击者是拿不到这部分数据的,所以对于一些查询类功能,即便没有做任何防御 CSRF 的措施,它也几乎是没有利用价值的;而 XSS 由于可以执行js代码,这也就使得攻击者可以将它想要的数据发送到自己的服务器上,比如前面 XSS 章中提到的回传 cookie。

防御方法

1.【最保险】CSRF Token:通过服务器生成一个唯一的、不可预测的值,然后发送给客户端。当用户要执行敏感操作,比如提交表单的时候,要求客户端在请求包中携带上这个 CSRF Token,这样攻击者就很难去构造一个属于这个用户的有效请求,从而防止 CSRF 的发生。

2.SameSite cookie:该属性可以用于指定是否允许 Cookie 被跨站点请求使用。SameSite 属性有三个可选值:

(1) Strict(严格模式):Cookie 在任何跨站点请求中都不会被发送,这样可以防止 CSRF 攻击。但这可能会导致某些功能受限,特别是当网站需要在跨站点请求中使用 Cookie 时。

(2) Lax(宽松模式):Cookie 只在顶级导航(例如从外部网站链接进入的页面)以及 GET 方法的跨站点请求中发送。POST、PUT、DELETE 等请求不会发送 Cookie。这样可以在一定程度上保护用户的隐私和防范 CSRF 攻击。

(3) None(无限制模式):Cookie 在任何情况下都会被发送,即使是跨站点请求。需要注意的是,使用 None 模式时,必须同时设置 Secure 属性(仅通过 HTTPS 传输)才能生效,并且该模式存在一定的安全风险和隐私问题,应谨慎使用。一篇文章学会csrf

3.【可能会有坑】校验 Referer 头:有的网站可能通过验证请求的 referer 是否来自网站自己的域名来防止 CSRF 攻击,但是在一些情况下,这种验证可能无法起到防止 CSRF 的作用

案例详解

任务简报

这个实验室在修改邮箱的地方存在一个CSRF漏洞,要解决这个实验室你需要制作一个 POC 来修改受害者的邮箱。

任务过程

1.使用提供的账号密码登录实验室 wiener:peter一篇文章学会csrf

2.可以看到此时默认邮箱是 [email protected] ,我们先随便修改一个抓个包,修改后的 [email protected]

  • 一篇文章学会csrf

3.我们可以看到,这里只提交了一个修改后的邮箱,这里我们可以使用 burp 自带的功能来生成 POC

  • 一篇文章学会csrf

4.现在我们要做的就是把邮箱修改成我们自己的 [email protected],所以我们只需要修改 value 中的值就可以了

  • 一篇文章学会csrf

5.对于我们平时的测试来说,下一步点击 Test in browser -> copy 然后在同一个浏览器打开,来模拟受害者点击我们传播的 url 即可

  • 一篇文章学会csrf一篇文章学会csrf一篇文章学会csrf

6.此时我们会发现邮箱已经被改变了,对于日常的测试来说到这里就可以了,但是想要通过这个实验室,还需要后面的几步,这里让我们回到第4步,同时把邮箱改回 [email protected],以便下面的演示

一篇文章学会csrf

7.将我们刚才修改后的POC复制到,实验室对应的利用服务器上

  • 一篇文章学会csrf

8.将 HTML 复制到 body 中,同时点击 store 保存

  • 一篇文章学会csrf

9.现在我们就要模拟受害者在登录了 web-security-academy.net 这个网站的时候,受到攻击者诱导,在攻击者的网站 exploit-server.net 上点击了一个功能 (View exploit) 然后浏览器自动发起修改 web-security-academy.net 上用户绑定邮箱的场景。点击 View exploit

  • 一篇文章学会csrf一篇文章学会csrf

10.可以看到,网站自动跳转到 web-security-academy.net 并将邮箱从 [email protected] 修改为了 [email protected],那么点击 deliver exploit to victim 将你的 POC 传播给受害者们就可以通过这个实验室了

  • 一篇文章学会csrf

绕过思路

CSRF token 绕过

在本章节,重点在于各种情况下的绕过 CSRF token 的方式,一些重复性的操作就不再赘述

未限制请求方法

这种漏洞出现的原因就是研发人员没有限制请求方法,且没有完善的逻辑来处理各种情况

任务简报

这个实验室的修改邮箱处存在 CSRF 漏洞,并且它试图通过 CSRF token 来阻止CSRF攻击

任务过程

  1. 前面的过程我们就直接略过,我们看看它的修改邮箱的功能是如何实现的

  • 一篇文章学会csrf

2.这里我们可以看到是存在一个 CSRF token 的,我们删了它看看会怎么样,万一这玩意儿就是用来吓唬人的呢

  • 一篇文章学会csrf

3. 很遗憾,看来他还是有用的,但是不要放弃,我们都知道由于一些奇奇怪怪的原因,研发在写代码的时候可能会出现一些奇怪的 bug,可能他们没有想到有些用户他不喜欢老老实实的使用他们开发的系统,这里我们用的就是这个思路

4. 当你在使用 get 方法提交一些数据的时候,我们也可以使用 POST 来提交,那这里我们能不能用 get 来修改邮箱呢,那我们就试试

  • 一篇文章学会csrf一篇文章学会csrf

5. surprise,它居然可以,那我们删了 CSRF 这个参数看看它的处理逻辑有没有变化

  • 一篇文章学会csrf一篇文章学会csrf

6. 哈 get 方法居然没有校验 CSRF 了,那我们就继续老样子,右键生成 POC,保存到 利用服务器 就完事了

  • 一篇文章学会csrf一篇文章学会csrf

7. 收工下班

  • 一篇文章学会csrf

未校验参数是否存在

这种漏洞出现的原因就是没有校验参数的完整性。

任务简报

这个实验室的修改邮箱处存在 CSRF 漏洞,并且它试图通过 CSRF token 来阻止CSRF攻击

任务过程

  1. 老样子,我们看看他是怎么修改邮箱的

  • 一篇文章学会csrf

2. 和上面的案例没什么区别,那我们还是看看删除 CSRF 这个参数的结果怎么样

  • 一篇文章学会csrf

3. 哈 这个更简单了,直接干,右键生成 POC,上传 利用服务器,就完事了,这里就不赘述了

使用公共的 CSRF token 池

这种情况是由于这个应用没有将一个用户的 session 和他的 CSRF token 进行绑定,而是做了一个公共的 CSRF token 池,只要是这个池里的 token,都是有效的。

那么大家应该也有思路了,那就是直接自己登录上去获取到一个 token 即可绕过

任务简报

这个实验室的修改邮箱处存在 CSRF 漏洞,并且它试图通过 CSRF token 来阻止CSRF攻击

任务过程

  1. 这个演示需要两个账号 wiener:peter 和 carlos:montoya

  2. 我们先登录 wiener,看看它的修改邮箱是怎么实现的

  • 一篇文章学会csrf

3. 请求包还是一样的,我们看下上面的两种方式还能不能绕过 (当然不行,这里就不演示了)

4.这里我们先记录一下wiener的token值 roVAju4ZU5DLlKwBO9n0GzqvERfXumk8,然后登出当前账号,再次重新登录 carlos 看看刚才的 token 还能不能使用

  • 一篇文章学会csrf

5. 这里我们使用 Intercept 拦截修改 CSRF 的值之后发现是无效的,现在就有几种可能,一是 token 和 session 绑定,不能使用别人的 token 来绕过校验;二是 token 是一次性的,用后即焚;三的话就是我们的主题 是公共token池,但是用后即焚

6. 第一种可能上面已经验证过了,那么我们来验证第二种,其实也很简单,再修改一下邮箱,看看服务器有没有下发新的 CSRF token 就行了,或者看看两次传递的 token 是不是一样的

  • 一篇文章学会csrf

7. 不太妙啊,居然是一次性的,那我们只能试试第三中情况了,让我们保存下现在的 token 不要用它 0wSAAuvFa8JFRSpD1BgSQifWo75xeJyt 然后登出 carlos 登录 wiener 在修改邮箱的时候替换 CSRF 的值,看看结果如何

  • 一篇文章学会csrf一篇文章学会csrf

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

9. 思路清晰之后我们只有重复上面案例中的过程就可以了,这里就不再赘述了

csrf token 直接在 cookie 中获取

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

这样的防御思路是通过 cookie 和 请求体参数 双重提交token,服务器判断两个值是否相等来防御 csrf 漏洞,这样做的好处是服务器不需要进行多余的计算、保存 csrf token 值,在生成 cookie 的时候就可以一起完成。但是就像上面说的当用户可以定义 se-cookie 的时候,这种做法就不再安全了。

任务简报

这个实验室的修改邮箱处存在 CSRF 漏洞,并且它试图通过双重提交 CSRF token 来阻止CSRF攻击

任务过程

  1. 我们还是来看它的修改邮箱是如何实现的

  • 一篇文章学会csrf

2. 这里可以看出他们是相同的,那么我们就需要一个地方来想办法注入 set-cookie,巧的是在搜索这里存在一个 CRLF 漏洞 payload %0d%0aSet-Cookie:%20csrf=123456%3b%20SameSite=None

  • 一篇文章学会csrf

3. 那么我们就可以在自己的服务器上(exploit-server.net)构造一个响应,让它去请求 web-security-academy.net 上的资源,然后发起一个请求来实现 CRLF 注入,之后再发送请求去修改邮箱就好了,思路有个那下面就是payload了

4. 老样子我们先生成一个 CSRF 的POC

5. 下面我们来做一下修改,让它来实现我们的功能,其实只需要修改

  •   <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>

6. 上面的代码我们主要是利用了 img 标签去请求 web-security-academy.net 上的一个不存在的图片,当它发送这个请求的时候, web-security-academy.net 的 cookie 中的 csrf 键将被设置为 csrf=123456,当请求失败的时候,就会提交我们的 CSRF 代码来修改邮箱,那么我们来看看效果

  • 一篇文章学会csrf一篇文章学会csrf

7. 这样我们的攻击就完成了,后边提交通过实验室的过程就不再赘述了

绕过 referer 头校验

有些网站通可能会通过校验 referer 头来判断请求是不是来自自己的网站,并以此来防御 CSRF 漏洞,但是这种防御方法在某些情况下也可能会被绕过。

删除 referer 头

这种情况存在于开发人员在写代码的时候没有考虑到 referer 头不存在的情况下的处理逻辑,导致绕过了 referer 校验。

但由于 referer 头是浏览器自动添加的请求头,所以通过上面的方式去要求 referer 头等于某个特定的值来绕过 referer 校验是不可行的。

知识点:meta 标签用于提供关于 HTML 文档的元数据信息,也可以用来控制客户端发起请求的时候是否携带某个请求头,如

任务简报

本实验室在修改账号邮箱的地方存在 CSRF 漏洞,但是网站通过 referer 头进行 CSRF 防御,通过 exploit-server 修改账号的邮箱来通关本实验室

点击进入靶场

任务过程

  1. 前面的过程我们先跳过,直接看看他是怎么发起修改邮箱的请求的

  • 一篇文章学会csrf

2. 这里可以看到成功修改的话会自动跳转,同时请求包里有 referer 头,那我们看看把他该一下会是什么响应

  • 一篇文章学会csrf

3. 这里报错无效的 referer,那我们看看删了它会有什么响应,毕竟对于很多情况下删除某些参数往往会有意外之喜

  • 一篇文章学会csrf

4. 可以看到同样修改成功了,那么下一步就是如何在 POC 里让它不发送 referer 头了,这里就用上我们上面提到的 meta 标签了,下面我们看看有 meta 和没有的区别

5. 老样子,还是生成一个 POC

  • 一篇文章学会csrf

6. 可以看到,这样的POC发送的请求是含有 referer 头的,那我们给它稍微加点料 payload

  • 一篇文章学会csrf

7. 神奇的事情发生了,referer 头没有了,那就意味着这个referer校验被我们绕过了,收工下班

包含目标网址的域名

还有一种情况是,对方的校验逻辑太过简单,比如检验 referer 是否以自己的域名开始,或者是否包含自己的域名 比如(if "www.baidu.com" in referer....)

这两种都可以用一种简单的办法绕过,那就是买一个域名,然后自己添加一个含有目标站点的子域名,比如 www.baidu.com.test.cn,其中的 www.baidu.com 就是子域名

对于后面的查看referer是否包含自己的域名,可以有一个简单的办法,比如在 uri 里加上它的值就好了,比如 history.pushState('', '', '/?www.baidu.com')

知识点:history.pushState 允许你更改浏览器历史记录中的当前URL而不重新加载页面,简单的说就是可以在不刷新页面的情况下修改你在状态栏的url

以百度为例,正常状态下它的地址栏是 www.baidu.com

一篇文章学会csrf

我们在控制台执行 history.pushState("","","/?^_^"),它的url就变成了 https://www.baidu.com/?^_^

一篇文章学会csrf

这就意味着,我们可以虽然不能定义 referer 的域名,但是可以定义referer 的 uri 来绕过 (if "www.baidu.com" in referer....) 的校验,那么理论成立,实践开始

任务简报

本实验室在修改账号邮箱的地方存在 CSRF 漏洞,但是网站通过 referer 头进行 CSRF 防御,通过 exploit-server 修改账号的邮箱来通关本实验室

点击进入靶场

任务简报

  1. 老样子,直接看它的修改邮箱的请求包

  • 一篇文章学会csrf

2. 没什么东西,看看referer是怎么校验的吧(删掉不好使,就不试了)

  • 一篇文章学会csrf一篇文章学会csrf

3. 可以看到,上面的两种方法都能绕过,那就说明是校验 referer 中是否含有域名,那我们还是生成 POC,然后稍微修改一下 payload history.pushState("", "", "/?0afc003404932ab58ac96e4e005700a5.web-security-academy.net")

  • 一篇文章学会csrf

4.这里可以看到,虽然我们加上了 history.pushState("", "", "/?0afc003404932ab58ac96e4e005700a5.web-security-academy.net") 但是它请求的时候 referer 并没有包含其中自定义的 uri。这是因为现在浏览器出于安全考虑会在请求的时候删除 referer 中的查询字段,但是这个也是可以解决的,不过就需要有点钞能力了,你可以租个服务器,设置响应头 Referrer-Policy: unsafe-url ,这样再次请求的时候就不会删掉你referer中的查询值了

5. 这里我们使用靶场自带的利用服务器来演示

  • 一篇文章学会csrf

6. 配置完成之后点击 store,然后访问上面的url

  • 一篇文章学会csrf一篇文章学会csrf一篇文章学会csrf

7. 可以看到在访问 我们利用服务器上的页面之后,其正常响应了 referrer-policy,之后再次请求目标网站的时候,客户端就没有删除referer 头里的查询参数了,至此绕过也就完成了,收工下班

原文始发于微信公众号(隐雾安全):一篇文章学会csrf

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年1月23日12:06:32
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   一篇文章学会csrfhttp://cn-sec.com/archives/2421352.html

发表评论

匿名网友 填写信息