简体   繁体   English

PHP | 防止 CSRF 攻击

[英]PHP | prevent CSRF attacks

I know perfectly well that preventing tampering with a form is impossible.我非常清楚防止篡改表格是不可能的。

But I want to ask, by implementing this function that generates a random number in a page hosting a form and echoing it in a hidden input field但我想问一下,通过实现这个 function 在托管表单的页面中生成一个随机数并在隐藏的输入字段中回显它

function makeRandomString($bits = 256) {
    $bytes = ceil($bits / 8);
    $return = '';
    for ($i = 0; $i < $bytes; $i++) {
        $return .= chr(mt_rand(0, 255));
    }
    return $return;
}

if at the time of submitting, I checked with a query if that code already exists in the table of random_codes created before, if it exists, it blocks everything, and if it does not exist, it inserts it and executes the query.如果在提交时,我通过查询检查了该代码是否已存在于之前创建的 random_codes 表中,如果存在,则阻止所有内容,如果不存在,则插入并执行查询。

Could that be a good thing?这会是一件好事吗?

You should not create your custom implementation, there are already well-known solutions to this problem in pretty much every language and framework.您不应该创建您的自定义实现,几乎每种语言和框架都有针对此问题的众所周知的解决方案。

A few obvious issues with your method:您的方法存在一些明显的问题:

  • mt_rand() is not cryptographically random and should not be used for this purpose mt_rand()不是加密随机的,不应用于此目的
  • if you store the generated values in a table, an attacker can store their own values to the same table and use it in the context of a victim user's session, unless these values are also tied to an actual user如果将生成的值存储在表中,攻击者可以将自己的值存储到同一个表中,并在受害者用户的 session 的上下文中使用它,除非这些值也与实际用户相关联
  • this will require a separate database lookup to check this token every single time (instead of storing it in the session)这将需要单独的数据库查找来每次检查此令牌(而不是将其存储在会话中)
  • you have not mentioned invalidating these values, would they be single use and deleted when received?您没有提到使这些值无效,它们是否会被一次性使用并在收到时被删除? that would be a UX disaster especially with javascript-heavy applications, and also a potential race condition这将是一场 UX 灾难,尤其是对于 javascript-heavy 应用程序,以及潜在的竞争条件
  • some of the characters generated will not be printable which might cause issues with hidden fields生成的某些字符将无法打印,这可能会导致隐藏字段出现问题
  • (if the $bits parameter is not disivisble by 8, you will generate more bits, which is very counter-intuitive) (如果$bits参数不能被 8 整除,就会产生更多的位,这很反直觉)
  • and so on...等等...

It's a lot easier to just use a known good implementation, rolling your own is trickier than you might think.使用已知的良好实现要容易得多,滚动自己的实现比您想象的要棘手。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM