PortSwigger Academy | Cross-site request forgery (CSRF) : 跨站请求伪造

在本节中,我们将解释什么是跨站点请求伪造,描述一些常见CSRF漏洞的示例,并解释如何防止CSRF攻击。

什么是CSRF?

跨站点请求伪造(也称为CSRF)是一个Web安全漏洞,攻击者可以利用该漏洞诱使用户执行他们不打算执行的操作。 它允许攻击者部分规避同源策略,该策略旨在防止不同的网站相互干扰。

在这里插入图片描述

CSRF攻击有什么影响?

在成功的CSRF攻击中,攻击者会导致受害者用户无意中执行操作。 例如,这可能是更改其帐户上的电子邮件地址,更改其密码或进行资金转帐。 根据操作的性质,攻击者可能会完全控制用户的帐户。 如果受感染的用户在应用程序中具有特权角色,则攻击者可能能够完全控制所有应用程序的数据和功能。

CSRF如何工作?

为了使CSRF攻击成为可能,必须具备三个关键条件:

  • 相关动作。 攻击者有理由诱使应用程序中发生某种动作。 这可能是特权操作(例如,修改其他用户的权限)或对用户特定数据的任何操作(例如,更改用户自己的密码)。

  • 基于Cookie的会话处理。 执行该操作涉及发出一个或多个HTTP请求,并且该应用程序仅依靠会话cookie来标识发出请求的用户。 没有其他机制可以跟踪会话或验证用户请求。

  • 没有不可预测的请求参数。 执行该操作的请求不包含攻击者无法确定或猜测其值的任何参数。 例如,当使用户更改密码时,如果攻击者需要知道现有密码的值,则该功能不会受到攻击。

例如,假设一个应用程序包含一个功能,该功能使用户可以更改其帐户上的电子邮件地址。 用户执行此操作时,将发出如下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所需的条件:

攻击者会对更改用户帐户上的电子邮件地址的操作感兴趣。 执行此操作后,攻击者通常将能够触发密码重置并完全控制用户的帐户。

该应用程序使用会话cookie来标识哪个用户发出了请求。 没有其他令牌或机制来跟踪用户会话。

攻击者可以轻松确定执行操作所需的请求参数的值。

在满足这些条件的情况下,攻击者可以构建包含以下HTML的网页:

<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(假设未使用SameSite cookie)。

易受攻击的网站将以正常方式处理请求,将其视为由受害者用户发出,并更改其电子邮件地址。

注意
尽管通常基于cookie的会话处理来描述CSRF,但它也出现在应用程序自动向请求中添加一些用户凭据的其他情况下,例如HTTP Basic身份验证和基于证书的身份验证。(就是说后面两种方式也受到CSRF的影响,不过我不太确定)

使用SameSite Cookie防御CSRF

一些网站使用SameSite cookie防御CSRF攻击。

SameSite属性可用于控制是否以及如何在跨站点请求中提交cookie。 通过在会话cookie上设置属性,应用程序可以防止默认的浏览器行为——无论它们来自何处,都自动向请求添加cookie。

服务器发出cookie时,会将SameSite属性添加到Set-Cookie响应标头中,并且可以为该属性赋予两个值:StrictLax。 例如:

SetCookie: SessionId=sYMnfCUrAlmqVVZn9dqevxyFpKZt30NN; SameSite=Strict;

SetCookie: SessionId=sYMnfCUrAlmqVVZn9dqevxyFpKZt30NN; SameSite=Lax;

如果SameSite属性设置为Strict,则浏览器将不会在来自另一个站点的任何请求中包含cookie。 这是最防御性的选项,但是它可能会损害用户体验,因为如果已登录的用户遵循指向站点的第三方链接,那么他们似乎将无法登录,因此需要再次登录 以正常方式与网站互动。

如果SameSite属性设置为Lax,则浏览器将在来自另一个站点的请求中包含cookie,但前提是必须满足两个条件:

  • 该请求使用GET方法。 使用其他方法(例如POST)的请求将不包含cookie。

  • 该请求来自用户的顶级导航,例如单击链接。 其他请求(例如由脚本启动的请求)将不包含cookie。

然后,在Lax模式下使用SameSite cookie确实可以部分防御CSRF攻击,因为作为CSRF攻击目标的用户操作通常是使用POST方法实现的。 这里有两个重要警告:

  • 一些应用程序确实使用GET请求实施敏感操作。

  • 许多应用程序和框架可以容忍不同的HTTP方法。 在这种情况下,即使应用程序本身通过设计采用了POST方法,它实际上也会接受切换为使用GET方法的请求。

出于上述原因,不建议仅依靠SameSite cookie来防御CSRF攻击。 但是,与CSRF令牌结合使用时,SameSite cookie可以提供额外的防御层,可以减轻基于令牌的防御中的任何缺陷。

如何构造CSRF攻击

手动创建CSRF攻击所需的HTML可能很麻烦,特别是在所需的请求包含大量参数或请求中存在其他怪癖的情况下。 构造CSRF漏洞最简单的方法是使用Burp Suite Professional内置的CSRF PoC生成器:

  • 在Burp Suite Professional中的任意位置选择要测试或利用的请求。

  • 从右键单击上下文菜单中,选择Engagement tools/Generate CSRF PoC

  • Burp Suite将生成一些HTML,这些HTML会触发选定的请求(减去cookie,该cookie将由受害者的浏览器自动添加)。

  • 您可以在CSRF PoC生成器中调整各种选项,以微调攻击的各个方面。 您可能需要在某些不常见的情况下执行此操作,以处理请求的古怪功能。

  • 将生成的HTML复制到网页中,在登录到易受攻击的网站的浏览器中查看它,并测试是否成功发出了预期的请求以及是否发生了所需的操作。

Lab: CSRF vulnerability with no defenses

先登录自己的账户,然后拦截更改邮箱的数据包
在这里插入图片描述
然后把生成的html贴到exp服务器
在这里插入图片描述

然后把url发送给受害者即可
https://ace21f3c1e1c542a80ee05b901a20021.web-security-academy.net/exploit
在这里插入图片描述
好吧,exp服务器必须这么写才能完成这个实验室,换一下url即可

<form method="POST" action="https://ac611f261e9f543f80da05bc00890032.web-security-academy.net/email/change-email">
     <input type="hidden" name="email" value="1@1.com">
</form>
<script>
      document.forms[0].submit();
</script>

如何进行CSRF攻击

跨站点请求伪造攻击的传递机制与反射的XSS基本上相同。 通常,攻击者会将恶意HTML放到他们控制的网站上,然后诱使受害者访问该网站。 这可以通过电子邮件或社交媒体消息向用户提供指向网站的链接来完成。 或者,如果将攻击置于流行的网站中(例如,在用户评论中),他们可能只是在等待用户访问该网站。

请注意,一些简单的CSRF漏洞利用GET方法,并且可以通过易受攻击的网站上的单个URL完全自包含。 在这种情况下,攻击者可能不需要使用外部站点,并且可以在易受攻击的域上直接向受害者提供恶意URL。 在前面的示例中,如果可以使用GET方法执行更改电子邮件地址的请求,则自包含式攻击将如下所示:
<img src="https://vulnerable-website.com/email/change?email=pwned@evil-user.net">

XSS vs CSRF

在本节中,我们将解释XSS和CSRF之间的区别,并讨论CSRF令牌是否可以帮助防止XSS攻击。

XSS和CSRF有什么区别?

跨站点脚本(XSS)允许攻击者在受害用户的浏览器中执行任意JavaScript。

跨站点请求伪造(CSRF)允许攻击者诱使受害用户执行他们不打算执行的操作。

XSS漏洞的后果通常比CSRF漏洞更为严重:

  • CSRF通常仅适用于用户能够执行的操作的子集。 通常,许多应用程序都实现CSRF防御,但是忽略了暴露的一两个动作。 相反,成功的XSS利用通常可以诱使用户执行用户能够执行的任何操作,而不考虑出现漏洞的功能。

  • CSRF可以描述为“单向”漏洞,因为尽管攻击者可以诱使受害者发出HTTP请求,但他们无法从该请求中获取响应。 相反,XSS是“双向”的,因为攻击者的注入脚本可以发出任意请求,读取响应并将数据泄露到攻击者选择的外部域。

CSRF令牌可以阻止XSS攻击吗?

通过有效使用CSRF令牌,确实可以防止某些XSS攻击。 考虑一个简单的反射XSS漏洞,可以像这样简单地加以利用:

https://insecure-website.com/status?message=<script>/*+Bad+stuff+here...+*/</script>

现在,假设易受攻击的函数包含CSRF令牌:

https://insecure-website.com/status?csrf-token=CIwNZNlR4XbisJF39I8yWnWX9wX4WFoz&message=<script>/*+Bad+stuff+here...+*/</script>

假设服务器正确地验证了CSRF令牌,并拒绝了没有有效令牌的请求,则该令牌确实阻止了XSS漏洞的利用。 这里的线索是名称:“跨站点脚本”,至少以其反映的形式,涉及跨站点请求。 通过阻止攻击者伪造跨站点请求,该应用程序可以防止对XSS漏洞的轻率利用。

这里有一些重要的警告:

  • 如果在不受CSRF令牌保护的功能内,站点上其他任何地方都存在反射的XSS漏洞,则可以以常规方式利用该XSS。

  • 如果站点上任何地方都存在可利用的XSS漏洞,则可以利用该漏洞使受害用户执行操作,即使这些操作本身受CSRF令牌保护也是如此。 在这种情况下,攻击者的脚本可以请求相关页面获得有效的CSRF令牌,然后使用该令牌执行受保护的操作。

  • CSRF令牌不能防止存储的XSS漏洞。 如果受CSRF令牌保护的页面也是存储的XSS漏洞的输出点,则可以以通常的方式利用该XSS漏洞,并且当用户访问该页面时,将执行XSS有效负载。

防止CSRF攻击

防御CSRF攻击的最可靠方法是在相关请求中包含CSRF令牌。 令牌应为:

  • 通常来说,会话​​令牌具有很高的熵,这是不可预测的。

  • 绑定到用户的会话。

  • 在执行相关操作之前,在每种情况下均经过严格验证。

SameSite cookie是对CSRF部分有效的另一种防御方法,可以与CSRF令牌结合使用。

CSRF token

在本节中,我们将解释什么是CSRF令牌,如何防御CSRF攻击以及应如何生成和验证CSRF令牌。

什么是CSRF令牌?

CSRF令牌是服务器端应用程序生成的唯一,秘密,不可预测的值,并以这样的方式传输到客户端,即它包含在客户端发出的后续HTTP请求中。 发出以后的请求时,服务器端应用程序将验证该请求是否包含预期的令牌,如果令牌丢失或无效,则拒绝该请求。

CSRF令牌可以使攻击者无法构造适合于馈送给受害者用户的完全有效的HTTP请求,从而防止CSRF攻击。 由于攻击者无法确定或预测用户CSRF令牌的值,因此他们无法使用应用程序满足请求所必需的所有参数来构造请求。

CSRF令牌应如何生成?

CSRF令牌应包含很大的熵,并且应该是高度不可预测的,并且通常具有与会话令牌相同的属性。

您应该使用加密强度伪随机数生成器(PRNG),该生成器附带创建时的时间戳以及静态密码。

如果除了PRNG的功能之外还需要进一步的保证,则可以通过将其输出与某些用户特定的熵连接起来来生成单独的令牌,并对整个结构进行强哈希处理。 这给试图基于颁发给令牌的样本分析令牌的攻击者带来了额外的障碍。

CSRF令牌应如何传输?

CSRF令牌应被视为机密,并在其整个生命周期中以安全的方式进行处理。 通常有效的方法是将令牌发送到使用POST方法提交的HTML表单的隐藏字段内的客户端。 提交表单后,令牌将作为请求参数包括在内:

<input type="hidden" name="csrf-token" value="CIwNZNlR4XbisJF39I8yWnWX9wX4WFoz" />
为了提高安全性,应将包含CSRF令牌的字段尽可能早地放置在HTML文档中,最好放在任何非隐藏的输入字段之前,以及将用户可控制的数据嵌入HTML内的任何位置之前。 这可以缓解攻击者可以使用制作的数据来操纵HTML文档并捕获其内容的一部分的各种技术。

将令牌放入URL查询字符串的另一种方法不太安全,因为查询字符串为:

  • 在客户端和服务器端的不同位置记录;

  • 易于在HTTP Referer标头中传输给第三方;

  • 可以在用户浏览器中显示在屏幕上。

某些应用程序在自定义请求标头中传输CSRF令牌。 这为试图预测或捕获另一个用户令牌的攻击者提供了进一步的防御,因为浏览器通常不允许跨域发送自定义标头。 但是,该方法将应用程序限制为使用XHR(与HTML表单相反)发出受CSRF保护的请求,并且在许多情况下可能被认为过于复杂。

CSRF令牌不应在Cookie中传输。

CSRF令牌应如何验证?

生成CSRF令牌后,应将其存储在服务器端的用户会话数据中。 当收到需要验证的后续请求时,服务器端应用程序应验证该请求是否包含与用户会话中存储的值匹配的令牌。 无论请求的HTTP方法或内容类型如何,都必须执行此验证。 如果该请求根本不包含任何令牌,则应以与存在无效令牌时相同的方式拒绝该请求。

常见的CSRF漏洞

最有趣的CSRF漏洞是由CSRF令牌验证中的错误引起的。

在前面的示例中,假设应用程序现在在更改用户密码的请求中包含CSRF令牌:

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

csrf=WfF1szMUHhiokx9AHFply5L2xAOfjRkE&email=wiener@normal-user.com

这应该防止CSRF攻击,因为它违反了CSRF漏洞的必要条件:应用程序不再仅依赖Cookie进行会话处理,并且请求包含一个参数,攻击者无法确定其值。 但是,可以通过多种方式来打破防御,这意味着该应用程序仍然容易受到CSRF的攻击。

CSRF令牌的验证取决于请求方法

当请求使用POST方法时,某些应用程序正确地验证了令牌,但是当使用GET方法时,跳过了验证。

在这种情况下,攻击者可以切换到GET方法来绕过验证并发送CSRF攻击:

GET /email/change?email=pwned@evil-user.net HTTP/1.1
Host: vulnerable-website.com
Cookie: session=2yQIDcpia41WrATfjPqvm9tOkDvkMvLm

Lab: CSRF where token validation depends on request method

将post方法换成 get方法

CSRF令牌的验证取决于令牌是否存在

如果令牌存在,某些应用程序会正确验证令牌,但是如果省略令牌,则跳过验证。

在这种情况下,攻击者可以删除包含令牌的整个参数(而不仅仅是令牌的值),以绕过验证并进行CSRF攻击:

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

email=pwned@evil-user.net

Lab: CSRF where token validation depends on token being present

删除csrf参数

CSRF令牌未绑定到用户会话

某些应用程序无法验证令牌与发出请求的用户属于同一会话。 而是,应用程序维护它已发出的全局令牌池,并接受出现在该池中的所有令牌。

在这种情况下,攻击者可以使用自己的帐户登录应用程序,获取有效令牌,然后在其CSRF攻击中将该令牌提供给受害者用户。

Lab: CSRF where token is not tied to user session

随便找一个没用过的csrf参数就行了

CSRF令牌绑定到非会话cookie

在上述漏洞的一种变体中,某些应用程序确实将CSRF令牌绑定到cookie,但没有绑定到用于跟踪会话的cookie。 当应用程序使用两种不同的框架(未集成在一起)时,很容易发生这种情况:一种用于会话处理,另一种用于CSRF保护。

POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 68
Cookie: session=pSJYSScWKpmC60LpFOAHKixuFuM4uXWF; csrfKey=rZHCnSzEp8dbI6atzagGoSYyqJqTz5dv

csrf=RhV7yQDO0xcq9gLEah2WVbmuFqyOq7tY&email=wiener@normal-user.com

这种情况很难利用,但仍然很脆弱。 如果该网站包含允许攻击者在受害者的浏览器中设置cookie的任何行为,则可能构成攻击。 攻击者可以使用自己的帐户登录应用程序,获取有效的令牌和关联的cookie,利用cookie的设置行为将其cookie放入受害者的浏览器中,并在CSRF攻击中将其令牌提供给受害者。

Lab: CSRF where token is tied to non-session cookie

回到原始浏览器中,执行搜索,将结果请求发送到Burp Repeater,然后观察到搜索词已反映在Set-Cookie标头中。 由于搜索功能没有CSRF保护,因此您可以使用此功能将Cookie注入受害者用户的浏览器中。

创建一个使用此漏洞的URL,将csrfKey cookie注入受害者的浏览器中:

/?search=test%0d%0aSet-Cookie:%20csrfKey=your-key

cookie设置行为甚至不必与CSRF漏洞存在于同一Web应用程序中。 如果所控制的Cookie具有适当的范围,则可以利用同一总体DNS域中的任何其他应用程序在目标应用程序中设置Cookie。 例如,可以利用staging.demo.normal-website.com上的cookie设置功能来放置提交到secure.normal-website.com的cookie。

CSRF令牌仅在Cookie中重复

在上述漏洞的另一种变体中,某些应用程序不维护任何已发布令牌的服务器端记录,而是复制cookie和request参数中的每个令牌。 当后续请求得到验证时,应用程序仅验证请求参数中提交的令牌是否与cookie中提交的值匹配。 有时将其称为针对CSRF的“双重提交”防御,之所以被提倡,是因为它易于实现并且避免了任何服务器端状态的需要:

POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 68
Cookie: session=1DQGdzYbOJQzLP7460tfyiv3do7MjyPw; csrf=R8ov2YBfTYmzFyjit8o2hKBuoIjXXVpa

csrf=R8ov2YBfTYmzFyjit8o2hKBuoIjXXVpa&email=wiener@normal-user.com

在这种情况下,如果网站包含任何cookie设置功能,则攻击者可以再次执行CSRF攻击。 在这里,攻击者无需获取自己的有效令牌。 他们只是发明了一个令牌(如果正在检查,则可能采用所需的格式),利用cookie设置行为将其cookie放置到受害者的浏览器中,并在CSRF攻击中将令牌提供给受害者。

Lab: CSRF where token is duplicated in cookie

还是cookie注入
/?search=test%0d%0aSet-Cookie:%20csrf=fake

针对CSRF的基于referer的防御

除了采用CSRF令牌的防御措施外,某些应用程序还使用HTTP Referer标头尝试防御CSRF攻击,通常是通过验证请求是否来自应用程序自己的域来进行。 这种方法通常效果较差,并且经常会绕过。

HTTP Referer标头(在HTTP规范中无意中拼写错误)是一个可选的请求标头,其中包含链接到所请求资源的网页的URL。 通常,当用户触发HTTP请求时,浏览器会自动添加它,包括单击链接或提交表单。 存在各种方法,允许链接页面保留或修改Referer标头的值。 通常出于隐私原因这样做。

Referer的验证取决于标头的存在

某些应用程序会在请求中包含Referer标头时对其进行验证,但是如果省略标头,则跳过验证。

在这种情况下,攻击者可以以某种方式设计其CSRF攻击,使受害者用户的浏览器在结果请求中删除Referer标头。 有多种方法可以实现此目的,但最简单的方法是在承载CSRF攻击的HTML页面中使用META标签:

<meta name="referrer" content="never">

Lab: CSRF where Referer validation depends on header being present

<meta name="referrer" content="no-referrer">

Referer验证的规避

某些应用程序以可以绕过的天真的方式验证Referer标头。 例如,如果应用程序简单地验证Referer包含其自己的域名,则攻击者可以将所需的值放在URL中的其他位置:

http://attacker-website.com/csrf-attack?vulnerable-website.com

如果应用程序验证了Referer中的域以期望值开头,则攻击者可以将此域放置为自己域的子域:

http://vulnerable-website.com.attacker-website.com/csrf-attack

Lab: CSRF with broken Referer validation

history.pushState("", "", "/?$original-domain")

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值