了解跨站请求伪造(CSRF 或 XSRF)

2025-06-04

了解跨站请求伪造(CSRF 或 XSRF)

此帖子还提供以下语言版本:葡萄牙语

在上一篇文章中,我们学习了如何在 Web 服务器上使用适当的清理技术来预防某些跨站脚本(XSS) 攻击。现在,让我们来看看另一个漏洞,它也会给未遵循适当安全措施的网页带来问题。

💡 如果您还没有阅读本系列的上一篇文章“使用 PHP 保护 GET 和 POST 请求”,我建议您阅读一下,因为为了理解以下概念,可能需要了解什么是HTTP 请求以及它们如何工作 — — 而且,它还可以帮助您提高网页的安全性。

介绍

让我们研究另一个最常见的 Web 漏洞:跨站请求伪造(CSRF),它通过让粗心的用户在已经通过身份验证的其他网页上执行不必要的操作来欺骗他们。

为了更好地说明这个问题,我们假设以下场景:您登录了银行账户,而该账户的 Web 服务器并不了解 Web 开发的最佳实践;您注意到一笔涉及某个您从未听说过的个人或公司的奇怪交易;您在另一个浏览器的标签页上搜索他们的名字,并访问了他们的网站。现在,即使您没有在这个未知的网页上进行身份验证或连接到您的银行账户,也没有使用(安全的)第三方质询-响应系统,我们虚构的恶意网页也可能已经更改了您的密码、转移了您的资金或使用您的凭据进行了购买。

听起来很吓人,对吧?尽管大多数现代浏览器都致力于创建“沙盒”并限制不属于同站政策的 Cookie 的使用,但互联网上仍有许多用户使用过时的 Web 浏览器,点击屏幕上弹出的每一个链接——其中大多数人声称,只要用户在特定日期和时间访问网站,或者完成一项他们甚至从未听说过的调查,他们就是赢家。

拿着绳子的锡罐里的企业家 - Vector Image.png

锡罐对话。由Wannapik设计

过去,互联网上一些访问量最大的网站都曾遭受过与 CSRF 相关的攻击,例如FacebookNetflixGmailYouTube 和《纽约时报》,此外,一些 Web 应用程序,例如Mozilla FirefoxApache HTTP Server ,也曾遭受过此类攻击。根据这篇论文,许多网站已经解决了这些问题,而其他一些网站(感谢开放开发者社区的努力)也已修复了这些问题。

通过在合法用户的会话中执行不必要的功能,这些恶意代理会利用其网页链接在我们的网站上发起任意操作,而我们的网站已经验证并存储了用户的会话 Cookie。这正是 XSRF 攻击最严重的部分:它不仅依赖于网站管理员,还依赖于浏览器的运行方式以及用户的行为。

CSRF 的工作原理

让我们重新审视一下在用户不知情的情况下执行攻击的恶意页面的示例。

CSRF 攻击成功的第一个条件是合法用户登录到一个可信网站,通过保存会话信息(如HTTP Cookies)来确保对用户凭证进行简易验证,因此他们不需要在每次向 Web 服务器发出请求时都告知他们的用户名和密码。

根据MDN Web 文档HTTP Cookies 通常用于判断两个请求是否来自同一浏览器。此外,它们还能记住无状态HTTP协议(​​或加密的HTTPS协议)的状态信息。

第二种情况是来自恶意网站的请求,该请求会诱使用户浏览器通过GETPOST请求向用户先前已进行身份验证的 Web 服务器发送请求。例如,可以使用 HTML 创建 Web 表单来实现,其目标页面是受信任服务器上的不安全网页。

简单来说,跨站请求伪造(CSRF) 攻击会伪造发送给受信任 Web 服务器的请求,因此它属于“跨站攻击”。下图解释了 CSRF 攻击的工作原理:攻击站点利用用户在 Web 浏览器上已验证的会话,以便在受信任的网站上执行受信任的操作。

souza2009.png

图片:Souza,2009 年。

出于本文的目的,我们不会在实际应用中介绍这种方法,因为我们的目标不是利用任何服务,而是为 Web 开发更好的实现。

示例#1:HTTP POST方法

如果目标页面未受 CSRF 保护,这些恶意代理就能利用用户的凭证成功执行任何他们想做的事情。例如:

<html>
<body>
    <form id="evil-form" action="http://my.trustful.bank/transfer?amount=123&account=stevie" method="POST">
        <button type="submit">Click here</button>
    </form>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

在这个例子中,假设该页面确实存在于互联网上,因此trustful.bank使用HTTP请求将美元金额发送给页面上123标识为的客户端stevie/transfer-funds

💡 这不是一个好的做法,所以我确信你的(真实)银行是安全的,并且受到了保护。如果它们不像其他网络服务器那样安全,后果将是灾难性的,并且可能引发一些法律问题,因为它们不符合当今大多数数据隐私和保护法规,例如GDPR 🇪🇺LGPD 🇧🇷

示例 2:自动行为

这些恶意代理甚至不需要用户直接与提交按钮交互就能实现发送结果。例如,他们可以将其更改为onload用户浏览器渲染页面时触发的事件,如下所示:

<html>
<body onload="document.getElementById('evil-form').submit();">
    <form id="evil-form" action="http://my.trustful.bank/transfer" method="POST">
        <input type="hidden" name="account" value="stevie"></input>
        <input type="hidden" name="amount" value="123"></input>
        <button type="submit">Click here</button>
    </form>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

此外,许多 Web 服务器同时允许HTTP GETPOST请求,因此 CSRF 攻击可能对它们都有效。

示例 #3:不使用 Web 表单

更糟糕的是,恶意代理并不局限于 HTML Web 表单。他们甚至会使用一个简单的img标签,例如:

<html>
<body>
    <img src="http://my.trustful.bank/transfer?amount=123&to=stevie" />
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

这种攻击还可以强制用户遵循重定向,方法是将其插入到 Web 服务器上的httpd.conf.htaccess文件中,如下例所示,取自《XSS 攻击:跨站点脚本漏洞和防御》(2007 年)一书:

Redirect 302 /a.jpg https://somebank.com/transferfunds.asp?amnt=1000000&acct=123456
Enter fullscreen mode Exit fullscreen mode

它将产生如下请求:

GET /a.jpg HTTP/1.0
Host: ha.ckers.org
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
Accept: image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Referer: http://somebank.com/board.asp?id=692381
Enter fullscreen mode Exit fullscreen mode

服务器响应如下:

HTTP/1.1 302 Found
Date: Fri, 23 Mar 2007 18:22:07 GMT
Server: Apache
Location: https://somebank.com/transferfunds.asp?amnt=1000000&acct=123456
Content-Length: 251
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title></head><body>
<h1>Found</h1>
<p>The document has moved <a href="https://somebank.com/transferfunds.asp?amnt=1000000&amp;acct=123456">here</a>.</p>
</body></html>
Enter fullscreen mode Exit fullscreen mode

在这个例子中,每当 Web 浏览器执行重定向时,它都会回到通知的位置,并且HTTP Cookies完好无损,但引用的URL可能不会更改为重定向页面,这会使情况变得更糟,因为用户可能无法轻易检测到引用的 *URL*。

谁能想到一条线路就能带来这么多麻烦呢?所以,请记住:网络安全永远不嫌多,总有新东西需要学习和运用。

CSRF 和/或 XSS 攻击

站脚本攻击(XSS)和跨站请求伪造攻击(CSRF)有一些共同点,但它们并不相同。而且,它们可以一起使用和实施。

这种组合的一个例子是“ MySpace 蠕虫”(也称为“Samy 蠕虫”或“JS.Spacehero 蠕虫”),由当时 19 岁的开发人员 Samy Kamkar 于 2005 年开发,他通过添加几个单词创建了一个脚本,感染了一些人的个人资料,以便在这个社交网络上与他成为好友,但随后迅速蔓延开来,收到了近百万个好友请求。

myspace_from_vice.png

这是 Kamkar 的 MySpace 个人资料的一部分,显示了他在 2005 年写完剧本后结识了多少朋友。图片来源:VICE

尽管这种攻击最终是无害的,但如果没有人注意到或认真对待这种威胁,恶意代理可能会注入恶意代码,从而危及整个网络服务器。

💡跨站请求伪造(XSRF) 也称为 CSRF,取自跨站脚本(XSS) 的首字母缩写。之所以这样称呼,可能是为了避免与用于网页样式化的层叠样式表(CSS) 混淆,CSS 的首字母缩写也是 CSS。

如何防止CSRF攻击

那么,我们如何防止CSRF攻击呢?我们需要做一些事情:

1. 保持你的网络浏览器为最新版本

你可能会惊讶地发现,竟然有这么多用户仍在日常使用过时的网络浏览器和应用程序。造成这种情况的原因数不胜数,例如缺乏信息(例如如何操作以及为什么),与特定版本的兼容性(很多情况下并不存在追溯兼容性),甚至公司合同的规范——我指的不仅仅是网络浏览器。

作为用户,首先要采取的措施是将 Web 浏览器更新到最新版本。最常用的应用程序使用WebKitGecko或其他浏览器引擎,这些引擎目前由开放的开发者社区开发和支持。他们意识到这些问题,并致力于在短期内解决这些问题。一些主流 Web 浏览器背后的公司也设有“漏洞赏金计划”,奖励那些发现可能危及用户数据和隐私的独特漏洞的安全研究人员。

如果您是开发人员,您应该提醒用户,过时的应用程序可能会导致一些问题,包括 CSRF 攻击,并且他们可能会将个人数据暴露给互联网上的恶意代理。此外,这种做法还能帮助您提供更好的用户体验,因为更新的浏览器还会包含新功能和 API,从而增强许多网站的可用性。

顺便说一句,最近,谷歌Mozilla宣布了其浏览器引擎安全性的几项改进,例如“隐私沙盒”、更好的HTTP Cookies策略和 JavaScript 阻止机制。

2.检查HTTP Referrer标头

现代网络浏览器上的大多数请求都包含两个元数据,可以帮助我们验证来源的位置:OriginReferrer标头信息。

作为开发者,每当向 Web 服务器发出请求时,您都可以检查OriginReferrer标头数据是否来自同一站点。如果不是,您可以忽略它,并且不要执行任何来自 的功能Origin

不幸的是,在少数情况下,这是不可能的,而且你可能会阻止来自使用公司代理或其他类似功能的用户的合法请求。此外,有很多方法可以伪造这些标头的信息,因此许多作者认为这可能不是保护 Web 服务器免受 CSRF 攻击的最佳方法。

3.实现 SameSite 属性

SameSite属性(RFC6265bis)可以真正帮助我们减轻 CSRF 攻击,因为如果未经授权的网站使用跨站点请求,他们将无法完成进入我们 Web 服务器的请求。

为了将HTTP Cookie 限制在同一站点位置,我们可以将此属性设置为HTTP响应标头来实现。这样,我们的HTTP Cookie 就可以限制在第一方或同一站点的上下文中。例如:

Set-Cookie: TOKEN=1bf3dea9fbe265e40d3f9595f2239103; Path=/; SameSite=lax
Enter fullscreen mode Exit fullscreen mode

根据MDN Web Docs,该SameSite属性可以接受以下三个值之一:

  • Lax — 如果SameSite未指定此属性,则为默认值;HTTP Cookie可以在用户导航至 Cookie 的源站时发送。它们不会在正常的跨站子请求(例如,将图片或框架加载到第三方网站)时发送,而是在用户导航至源站时发送(例如,点击链接)。
  • NoneHTTP Cookies将在所有上下文中发送,并且可以在原始请求和跨站请求中发送。这应该只在安全的上下文中使用,例如当Secure属性也设置时;
  • 严格HTTP Cookies只能与发起它的站点位于同一站点。

💡 如果您在 Web 服务器上处理个人敏感数据(例如用于用户身份验证的数据),则应为HTTP Cookies设置较短的生存期。此外,您应该将SameSite属性设置为StrictLax,这样未经身份验证的请求就不会有效地传送到 Web 服务器。

请注意,您应该将该SameSite属性与反 CSRF 令牌一起使用,因为某些HTTP 请求(尤其是GETHEADPOST方法)即使在请求不被允许的情况下也会执行,并且应该返回HTTP错误代码作为响应。无论如何,一个简单的请求已经在服务器端发出并执行了。幸运的是,还有其他方法可以解决这个问题,例如与由复杂且安全的数学方法生成的随机值一起使用。

4. 添加随机令牌

最常见的 CSRF 缓解方法之一是使用反 CSRF 令牌,这是一种随机、保密且唯一的令牌,会在请求发送到 Web 服务器时发送。每当发出请求时,Web 服务器都会检查这些数据:如果匹配,则允许继续处理;如果不匹配,则拒绝该请求。

此令牌可以为每个请求生成,存储在 Web 服务器上,然后插入到客户端的请求中(直接在 Web 表单上,或附加到HTTP请求),因此可以检测到从未经授权的位置向我们的 Web 服务器发出的请求。

如果令牌与属性一起使用,恶意代理将无法读取令牌,SameSite并且如果它们没有与 Web 服务器先前为此特定请求设置的令牌匹配的令牌,它们将无法继续执行我们网站上的任何功能。

这可以通过在与可信服务器相同的站点上指定反 CSRF 令牌并将其包含到新的 HTML Web 表单中来完成,如下所示:

<html>
<body>
    <form id="good-form" action="http://my.trustful.bank/transfer" method="POST">
        <input type="hidden" name="token" value="1bf3dea9fbe265e40d3f9595f2239103"></input>
        <input type="text" name="account" value="stevie"></input>
        <input type="text" name="amount" value="123"></input>
        <button type="submit">Submit</button>
    </form>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

在客户端,我们可以在 PHP 中设置一个反 CSRF 令牌,如下所示:

<?php
$_SESSION['token'] = bin2hex(random_bytes(16)); // 1bf3dea9fbe265e40d3f9595f2239103
?>
Enter fullscreen mode Exit fullscreen mode

仍然在客户端,如果我们使用 JavaScript,我们可以添加一个反 CSRF 令牌,并将其作为X-Header信息发送到XMLHttpRequest上。例如:

var token = readCookie(TOKEN);                       // Get the HTTP Cookie that we previously set, identified as "TOKEN"
httpRequest.setRequestHeader('X-CSRF-Token', token); // Then, send it as an "X-CSRF-Token" header information
Enter fullscreen mode Exit fullscreen mode

后续步骤🚶

如前所述,网络安全永无止境,总有新东西需要学习和应用。为了构建更安全的应用程序,请务必关注本系列的下一篇文章,并阅读进一步的参考资料,以获取有关 Web 开发最佳实践的更多详细信息。

如果您对如何构建更安全的应用程序有任何问题或建议,请在评论中分享。📣

参考

[1] Zeller, W. 和 Felten, EW (2008)。跨站点请求伪造:利用和预防。贝里希特,普林斯顿大学。https://www.cs.memphis.edu/~kanyang/COMP4420/reading/csrf.pdf

[2] 苏扎,J.(2009)。跨站脚本和跨站请求伪造。巴西利亚,巴西利亚大学。https://cic.unb.br/~rezende/trabs/johnny.pdf

[3] Seth Fogie、Jeremiah Grossman、Robert Hansen、Anton Rager 和 Petko D. Petkov。XSS 攻击:跨站点脚本漏洞与防御。Syngress,2007 年。

[4] “跨站请求伪造与您”,摘自Coding Horrorhttps://blog.codinghorror.com/cross-site-request-forgeries-and-you/

[5] “使用 HTTP cookies”,摘自MDN Web Docs(Mozilla 开发者网络):https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies

[6] “CSRF”,来自MDN Web Docs(Mozilla 开发者网络):https://developer.mozilla.org/en-US/docs/Glossary/CSRF

文章来源:https://dev.to/danilo/understanding-cross-site-request-forgery-csrf-or-xsrf-3d95
PREV
Kubernetes 图解:主题公园类比
NEXT
你唯一需要的生产力建议:两天规则