防止PHP中的csrf

yre*_*uta 22 php security kohana

  1. 要求在GET和POST参数中进行身份验证,而不仅仅是cookie;

  2. 检查HTTP Referer标头;

在维基百科上看到了这篇文章,我想知道如何应用它们

好的...我正在使用Kohana PHP框架,我有确定引用标头的工具,但我究竟要检查引用标头?framework函数只返回引用者的URL

以及如何验证GET和POST参数?反对什么?存储的信息?预期的类型?

lee*_*ers 46

为了防止CSRF,您需要验证一次性令牌,POST并与当前会话相关联.像下面这样的东西...

在用户请求删除记录的页面上:

confirm.php

<?php
 session_start();
 $token = isset($_SESSION['delete_customer_token']) ? $_SESSION['delete_customer_token'] : "";
 if (!$token) {
     // generate token and persist for later verification
     // - in practice use openssl_random_pseudo_bytes() or similar instead of uniqid() 
     $token = md5(uniqid());
     $_SESSION['delete_customer_token']= $token;
 }
 session_write_close();
?>
<html>
<body>
<form method="post" action="confirm_save.php">
 <input type="hidden" name="token" value="<?php echo $token; ?>" />
Do you really want to delete?
<input type="submit" value=" Yes " />
<input type="button" value=" No " onclick="history.go(-1);" />
</form>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

然后,当涉及到实际删除记录时:

confirm_save.php

<?php
 session_start();
 // validate token
 $token = isset($_SESSION['delete_customer_token']) ? $_SESSION['delete_customer_token'] : "";
 if ($token && $_POST['token'] === $token) {
   // delete the record
   ...
   // remove token after successful delete
   unset($_SESSION['delete_customer_token']);
 } else {
   // log potential CSRF attack.
 }
 session_write_close();
?>
Run Code Online (Sandbox Code Playgroud)

令牌难以猜测,每个删除请求都是唯一的,仅通过$ _POST接受,并在几分钟后过期(此示例中未显示过期).

  • 根据http://php.net/manual/en/function.uniqid.php,`uniqid()不得用于安全目的.使用加密安全随机函数/生成器和加密安全散列函数来创建不可预测的安全ID.` (2认同)
  • 当您在不同的选项卡中打开同一网页时,这是一个问题。由于在每个选项卡中都会再次生成随机值,因此用户必须坚持使用其当前选项卡。 (2认同)