【问题标题】:CSRF only needed for ajax仅 ajax 需要 CSRF
【发布时间】:2018-04-23 14:39:14
【问题描述】:

我最近一直在研究一种通过使用令牌来阻止 CSRF 攻击的方法。据我了解:

1) 用户登录,设置会话cookie登录并生成CSRF令牌并保存到会话中

2) 用户提交表单(带有令牌)并且它应该与会话中的令牌匹配

假设我有 page1.php,它有一个 sql SELECT 来获取所有用户的帐户信息,然后在同一页面中,我还有一个指向 page2.php 的 ajax 按钮,它可以更改帐户信息。显然我保护 page2.php 免受 CSRF 的影响(因为这是一个发布请求)但是我如何保护 page1.php?如果这个页面是通过 ajax 从远程源调用或在攻击者网站上放置一个 iframe,这肯定会打印所有受害者的帐户信息吗?

如果是这种情况,为什么我似乎找不到任何关于保护所有页面免受 CSRF 攻击的信息,而我只找到用于在 ajax 中防止 CSRF 攻击的资源?

【问题讨论】:

  • 假设您应该更担心此查询的 SQL 注入。
  • 除此之外,您不应该在没有首先确认他们已登录到会话的情况下公开用户数据。会话仍然适用于 Ajax。
  • 感谢您的观点,但是我想保持代码简洁明了,以了解问题的实际意义 - sql 注入不是本次讨论的主题
  • 安全是,当公然违反基本最佳实践时,你很难责怪我指出这一点。
  • 还有一些检查可以确保用户已登录,但如果会话和 cookie 仍在受害者浏览器上,那么攻击者仍然可以使用该信息对吗?

标签: php jquery ajax security


【解决方案1】:

假设页面上有一个 sql select 并且没有 请求发布。现在,如果要从远程源调用此页面 通过 ajax 或在他们的网站上放置 iframe,这肯定会打印出来 所有受害者的数据?

确保所有分发“机密”信息的请求(作为网页或作为 ajax 调用的数据(或将来的任何内容)确实验证存在有效的会话活动。如果不是,请确保服务器端部分不分发任何机密信息,而是抛出一个错误,并确保您的 ajax 客户端理解它并为普通用户做正确的事情(比如告诉他们他们没有登录并让他们解决这个问题)。

如果是这样的话,我怎么好像找不到任何东西 保护所有页面免受 CSRF 攻击,我只找到资源 在 ajax 中防止 CSRF 攻击?

对于常规的 post 请求,表单通常会输出一个隐藏的输入字段,该字段包含 CSRF 令牌。就是这样。

但请确保处理请求的代码验证隐藏字段是否存在并填写正确的值。

还要确保任何修改内容的请求都受到 CSRF 保护。例如。非 ajax 上下文中的删除按钮应通过发送和验证 CSRF 令牌来保护(因此该按钮最终会成为一个带有 CSRF 隐藏字段的表单。

【讨论】:

  • 感谢您的回答 :) 我非常接近将其标记为正确,尽管我还有另一个关于假设情况的问题。因此,我有一个带有 sql select 的 a.php,它可以提取所有用户帐户信息,例如,还有一个启动 b.php 的按钮。它确实有一个脚本可以检查用户是否在页面 a.php 上登录(从这里:stackoverflow.com/a/244907/3722330)所以很明显我保护页面 b.php 免受 CSRF 但我如何保护调用 a.php 的人启动选择如果那个说得通?当然选择仍然有效,因为用户将登录
  • CSRF = cross site:攻击者的链接可能让客户端访问并检索信息,但它不会发送给攻击者,而是发送给受害者。因此,在您的示例中,页面 a 上的选择结果会显示在受害者身上,可能会导致他们采取无根据的行动,但最终不会出现在攻击者身上。换句话说:CSRF 问题只有在攻击者有办法创建受害者有权执行但不愿意执行并诱使他们执行的更改(例如删除、添加或更改记录)时才会出现。
【解决方案2】:

假设您在http://application.com/mypage 有一个页面,其中包含一些数据和生成的 CSRF 令牌。攻击者创建http://attacker.com/attack,当application.com 的有效用户访问时,向application.com 发出请求(通过ajax 或iframe,没关系)以获取应用程序数据。标准 csrf。

这对攻击者不起作用的原因是同源策略。当受害者用户在attacker.com 上时,对application.com 的请求将是跨域的。如果它是 iframe,将显示数据,但攻击者.com 将无权访问它,它只会显示给可以查看 application.com 的用户。如果是 ajax 调用,同样适用,attacker.com 上的 javascript 将无法访问响应,由浏览器确保。

对于 ajax 调用,可以通过 application.com 在响应中发送的 access-control-allow-origin 和相关响应标头 (CORS) 显式启用对跨域响应的访问。

请注意,尽管是跨域的,但仍会进行调用(在某些情况下,预检请求会发挥作用,但我们现在不讨论)。只有响应是攻击者无法访问的,这足以阻止 csrf。

(另外作为旁注,application.com 应防止显示在 iframe 中,例如发送 x-frame-options: sameorigin 标头以防止点击劫持和类似攻击,但这不是问题。)

【讨论】:

  • 感谢您的回答!非常具有描述性,我很欣赏对 X-frame-options 的引用 :) 我已经改写了我原来问题中的示例,所以你所说的内容是否可以防止我所描述的内容?
  • 是的,在这种情况下,您将受到保护。您可以对实际更改内容的 POST 请求进行令牌检查。对于 page1 上的 GET,您不需要针对 CSRF 的保护,因为同源策略。如果攻击者从不同的域发出请求,他将无法访问响应,并且请求本身没有问题,因为没有任何变化。 (请注意,如果 GET 改变了某些东西,那确实是个问题。)
  • 感谢您的帮助 :) 那似乎已经回答了我的问题!
【解决方案3】:

我不确定我是否明白这一点,但 CSRF 的令牌应该是一个随机数,每次调用都会改变。

关于来自其他地方的呼叫,ajax 请求还应检查呼叫是否来自具有正确权利的有效用户,就像对站点的任何“常规”呼叫一样。

如果是这样的话,我怎么好像找不到任何东西 保护所有页面免受 CSRF 攻击,我只找到资源 在 ajax 中防止 CSRF 攻击?

您通常做的是在“常规”页面中使用的表单的隐藏输入中设置一个随机数。

【讨论】:

  • 不一定,每个请求都生成一个更安全,但并不总是需要。在大多数情况下,在会话期间只使用一个令牌是非常安全的,如下所示:stackoverflow.com/a/31683058/3722330
  • 我没有找到任何关于它“完全安全”的声明,也没有发现链接中提到的“大多数情况”。
  • 我还在你之前错过的最后一个问题中添加了一行。
  • 1) 我粘贴了错误的链接,我会尽快找到正确的链接 2) 我认为您误解了我的问题 - 我的意思是说一个页面会自动拉动用户仪表板数据而没有帖子启动后就没有办法阻止 CSRF 的发生......
  • 如果您在每种形式中更改 CSRF 令牌,您将阻止浏览器的后退功能,并阻止在您网站的不同部分为同一用户打开多个窗口。如果您觉得有必要在攻击者可能窃取 CSRF 令牌的情况下尝试阻止 CSRF,您可能最好缩短会话的生命周期(因为会话对攻击者来说比 CSRF 令牌更有价值)
猜你喜欢
  • 2013-07-21
  • 2011-06-17
  • 2012-02-23
  • 2015-10-28
  • 1970-01-01
  • 2018-08-15
  • 2018-12-28
  • 2014-05-06
  • 2016-01-04
相关资源
最近更新 更多