是否有针对 PHP 辅助的 CSRF 的有效服务器端预防技术?

信息安全 csrf 推荐人 卷曲
2021-09-01 21:25:34

我首先要说的是:我只是一个网络安全爱好者,而不是专家。因此,我将陈述我目前所知道的,请随时纠正我。

通过阅读,我了解到:

  • CSRF的存在
  • GET 和 POST 请求背后的基础知识
  • 令牌引用缓解技术
  • 如果目标网站存在 XSS 漏洞,如何检索Token
  • 引用者通过 HTTP 标头以明文形式传递并因此可能被欺骗的事实
  • cURL用于首先加载页面,获取令牌,并使用此令牌发送 POST 数据并获取页面 post-auth 内容

因此,我的问题如下:如果有人使用 PHP 脚本来加载托管 POST 表单的页面,获取随机生成的令牌,并使用与目标网站匹配的自定义“Referer”标头发送 POST 数据,我有什么办法吗?可以在我的服务器上做些什么来缓解这种情况?

2个回答

我认为您误解了 CSRF 攻击是如何工作的,以及为什么 CSRF 令牌可以防止它们。因此,让我们从一个工作原理开始。

攻击者欺骗受害者访问http://evil.com包含自动执行 POST 的表单http://bank.com/transfer?to=evilHacker&amount=1000000如果受害者已经登录到她的银行,带有会话 ID 的 cookie 将像往常一样由浏览器发送,银行服务器无法知道受害者实际上并没有打算转账。请注意,这依赖于浏览器将带有会话 ID 的 cookie 发送到bank.com.

那么 CSRF 令牌如何提供帮助?如果bank.com始终检查请求中是否存在该会话唯一的随机令牌,evil.com则无法伪造请求,因为运行该站点的邪恶黑客不知道令牌是什么。

推荐人检查以类似的方式工作。浏览器从站点发出的请求evil.com将具有evil.com而不是bank.com作为引用者。浏览器不允许修改引用标头,因此攻击者无法伪造。

那么你的攻击路线呢——让攻击者在她的服务器上使用 PHP 脚本请求站点以获取 CSRF 令牌?这是行不通的,因为攻击者不会得到受害者的 CSRF-token。令牌对于会话是唯一的,因此具有会话 ID 的 cookie。但攻击者不知道受害者拥有的会话 ID,因此她无法将其包含在请求中。

请注意与第一种情况的不同之处,即浏览器包含 cookie。这不可能在服务器上发生。

Anders 的回答解决了这个问题,但只提供了在会话中存储令牌副本的解决方案。也可以存储令牌客户端,只要它受到适当的保护以免受重放攻击 - 但这与会话劫持问题有很大的重叠......

if ($_REQUEST['token']) {
   if (validate($_REQUEST['token'], $_COOKIE['ctoken'])) {
     // do the protected thing....
   } else {
     // handle exception
   }
}
$token=sha1(openssl_random_pseudo_bytes(40)) . ":" . time();
$client_stored_token=encrypt($token, create_key);
set_cookie('ctoken',$client_stored_token);

function validate($token, $client_stored_token) 
{
    $client_token=decrypt($client_stored_token, create_key());
    @list($rand_bytes, $timestamp)=explode(':', $client_token);
    if ($rand_bytes==$token && time()-$timestamp<MAX_THRESHOLD) {
       return true;
    } 
    return false;
}
function create_key()
{
   return sha1($_SERVER['HTTP_USER_AGENT'] 
      .(int)(ip2long($_SERVER['REMOTE_ADDR'])/65536)
      .SOME_STATIC_SALT);
}

(也可以通过 window.name 传播令牌,但这需要更多考虑)。

安德斯指出:

浏览器不允许修改引用标头,因此攻击者无法伪造。

不幸的是,在各种浏览器中,referer 标头存在很多问题——如果你依赖它,你就会陷入困境。

引用者通过 HTTP 标头以明文形式传递并因此可能被欺骗的事实

即使是最复杂的 CSRF 和会话保护机制也很容易被 HTTP 连接上的 MITM 击败。这就是我们使用 HTTPS 的原因。