CSRF(跨站请求伪造)攻击和预防

CSRF(跨站请求伪造)是一种网络安全漏洞,当Web应用未能验证HTTP请求来源时可能发生。防止CSRF攻击的关键包括使用CSRF令牌、限定HTTP动词、设置'SameSite' cookie属性。确保登录端点也受CSRF保护,并考虑使用无cookie会话管理。应用现代Web框架的内置防护机制是有效的防御策略。

什么是 CSRF 漏洞?

当使用 cookie 进行会话管理的 Web 应用程序无法验证 HTTP POST 请求的来源时,通常会出现 CSRF(跨站点请求伪造)漏洞。

当 Web 应用程序通过使用 GET 方法进行更改而滥用 GET 方法时,也会发生这种情况。这两种情况都允许恶意网站代表登录用户执行不需要的操作。

如何防范 CSRF 漏洞?

按着这些次序。

  1. 使用您的应用程序平台/库提供的 CSRF 令牌。
  2. 请勿使用 POST、PUT、PATCH 或 DELETE 以外的其他 HTTP 动词进行更改。
  3. 使用“SameSite”指令保护您的 cookie。

同源政策

在开始之前,了解 SOP(Same Origin Policy)是很有帮助的,它是 Web 浏览器安全模型的核心和灵魂。这是一个或多或少说的规则:

  1. 如果两个 URL 的协议、端口(如果指定)和主机相同,则它们的来源相同。
  2. 任何来源的网站都可以自由地向任何其他GET来源发送、、、POST和请求。此外,该请求包括该来源的用户 cookie(包括会话 ID)。HEADOPTIONS
  3. 虽然可以发送请求,但来自一个来源的网站无法直接读取来自另一个来源的响应。
  4. 网站仍然可以从这些 HTTP 响应中消耗资源,例如通过执行脚本、使用字体/样式或显示图像。JSONP hack 利用了第四条规则(不要使用 JSONP)。
  5. 如果网站获得窗口句柄,则来自一个来源的网站可以限制访问另一个来源的窗口。最值得注意的是来自不同来源的窗口可以更改彼此的 URL ( anotherWindow.location.replace("https://www.evil.com")。

例如,这个网站的来源是在https://www.appsecmonkey.com/哪里,主机在哪里,并且没有指定端口(这是隐含的,因为协议)。protocolhttpswww.appsecmonkey.com443https

一个简单的例子

让我们假设用户可以像这样登录 AppSec Monkey 并更新他们的电子邮件地址:

POST /user/update-email/ HTTP/1.1
Host: www.appsecmonkey.com
Cookie: SessionId=ABC123
...

new_email=bob@example.com

后端代码可能看起来像这样(至少如果你使用 Django):

def update_email(request):
  new_email = request.POST['new_email']
  set_new_email(request.user, new_email)

现在假设有一个evil.example.com带有以下 HTML 表单和自动提交脚本的邪恶网站:

<form method="POST" action="https://www.appsecmonkey.com/user/update-email/">
  <input type="hidden" name="new_email" value="evil@example.com" />
</form>
<script type="text/javascript">
  document.badform.submit()
</script>

当当前登录的用户www.appsecmonkey.com进入恶意网站时,将代表用户自动提交 HTML 表单,并立即将以下 HTTP POST 请求发送到www.appsecmonkey.com

POST /user/update-email/ HTTP/1.1
Host: www.appsecmonkey.com
Cookie: SessionId=ABC123
...

new_email=evil@example.com

Bob 的电子邮件地址更改为evil@example.com.

CSRF 代币

防止这些攻击的常用方法是使用称为 CSRF 令牌的东西。它可以让您在 HTML 表单中添加一个隐藏的值,攻击者无法猜到。

<form method="POST" action="/user/update-email/">
  <input type="text" name="new_email" />
  <input type="hidden" name="csrf-token" value="SomeRandomValue123456" />
</form>

当另一个网站喜欢evil.example.com尝试提交表单时,网络服务器会拒绝 POST 请求,因为它不包含用户的 CSRF 令牌。

所有现代 Web 应用程序框架(SpringExpressSymfonyDjangoASP.Net MVC等)。物有所值有这样的 CSRF 保护机制,所以不要创建自己的.

这是你的第一道防线。

不要忘记登录端点

它也是一个漏洞,通常可以通过某种方式利用,如果恶意网站可以在不知不觉中使用他们的帐户登录您的用户。

为防止这种情况,请确保在登录表单中也使用 CSRF 令牌。

您应该将令牌绑定到预身份验证会话(当用户进行身份验证并为用户提供新的会话 ID 时,您应该将其丢弃,但这是另一回事)。

或者,如果您使用 OAuth/OIDC,请确保您state正确验证了参数(有关详细信息,请参见此处)。

在这两种情况下,现代应用程序框架都应该能够毫不费力地处理它。

注意你的 HTTP 动词

CSRF-token 机制倾向于只保护 POST 请求。因此,如果您接受 GET 请求,例如https://www.appsecmonkey.com/user/update-email?new_email=evil@example.com,无论您可能使用任何 CSRF 保护,您通常都容易受到攻击。

确保您不使用除 POST/PUT/PATCH/DELETE 之外的任何东西进行更改。

现代平台倾向于明确动词,但有时您必须小心遗留框架。

使用 SameSite cookie

现在的浏览器支持一个很酷的特性,叫做SameSite cookie。当您使用 设置 cookie 时SameSite=Lax,浏览器不会将其包含在跨站点 POST 请求中。

Set-Cookie: SessionId=123; ...other options... SameSite=Lax

就是这样,简单而有效。但是不要仅仅依靠这个特性来保证你的应用程序的安全。使用 CSRF 令牌作为您的主要防御,并应用 SameSite cookie 作为额外的保护层。

您还可以在SameSite=Strict模式下设置 cookie。在这种情况下,GET 请求也将受到保护。但是,如果您遵循上述注意 HTTP 动词的规则,这对于 CSRF 保护来说不是必需的。而且它会在某种程度上破坏功能,因为指向应用程序的链接将不再按预期工作(在打开选项卡/窗口时将不再登录用户)。

使用该Strict变体的好处是可以防止某些 XSS(跨站点脚本)攻击,因此您可能至少要考虑一下。

使用无 cookie 会话管理

CSRF 是一个影响使用 cookie 进行会话管理的应用程序的漏洞。避免它们的一种方法是使用其他东西,例如 JavaScript 会话令牌。但这种方法也有缺点。例如,XSS 攻击可以访问令牌。相比之下,Web 应用程序可以使用该HttpOnly属性保护 cookie 免受 JavaScript 代码的影响。

结论

CSRF 攻击可能很危险。幸运的是,只要您使用支持 CSRF 令牌并明确 HTTP 动词的体面、现代的应用程序平台,它们也很容易避免。SameSite cookie 为您的应用程序提供了出色的附加安全层,但不应仅依赖于安全性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值