gpt4 book ai didi

php - 如何使用 PHP 正确添加跨站请求伪造 (CSRF) token

转载 作者:IT老高 更新时间:2023-10-28 11:55:27 24 4
gpt4 key购买 nike

我正在尝试为我网站上的表单添加一些安全性。其中一种形式使用 AJAX,另一种是直接的“联系我们”形式。我正在尝试添加一个 CSRF token 。我遇到的问题是 token 有时只出现在 HTML“值”中。其余时间,该值为空。这是我在 AJAX 表单上使用的代码:

PHP:

if (!isset($_SESSION)) {
session_start();
$_SESSION['formStarted'] = true;
}

if (!isset($_SESSION['token'])) {
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
}

HTML:

<input type="hidden" name="token" value="<?php echo $token; ?>" />

有什么建议吗?

最佳答案

对于安全码,请不要这样生成 token :$token = md5(uniqid(rand(), TRUE));

试试这个:

生成 CSRF token

PHP 7

session_start();
if (empty($_SESSION['token'])) {
$_SESSION['token'] = bin2hex(random_bytes(32));
}
$token = $_SESSION['token'];

旁注:my employer's open source projects 之一是一项将 random_bytes()random_int() 反向移植到 PHP 5 项目中的倡议。它是 MIT 许可的,在 Github 和 Composer 上可用 paragonie/random_compat .

PHP 5.3+(或使用 ext-mcrypt)

session_start();
if (empty($_SESSION['token'])) {
if (function_exists('mcrypt_create_iv')) {
$_SESSION['token'] = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
} else {
$_SESSION['token'] = bin2hex(openssl_random_pseudo_bytes(32));
}
}
$token = $_SESSION['token'];

验证 CSRF token

不要只使用==甚至===,使用hash_equals() (仅限 PHP 5.6+,但可用于带有 hash-compat 库的早期版本。

if (!empty($_POST['token'])) {
if (hash_equals($_SESSION['token'], $_POST['token'])) {
// Proceed to process the form data
} else {
// Log this as a warning and keep an eye on these attempts
}
}

使用 Per-Form token 更进一步

您可以使用 hash_hmac() 进一步限制 token 仅可用于特定表单. HMAC 是一种特殊的键控散列函数,即使使用较弱的散列函数(例如 MD5),也可以安全使用。不过,我建议改用 SHA-2 系列哈希函数。

首先,生成第二个 token 用作 HMAC key ,然后使用如下逻辑来呈现它:

<input type="hidden" name="token" value="<?php
echo hash_hmac('sha256', '/my_form.php', $_SESSION['second_token']);
?>" />

然后在验证 token 时使用全等运算:

$calc = hash_hmac('sha256', '/my_form.php', $_SESSION['second_token']);
if (hash_equals($calc, $_POST['token'])) {
// Continue...
}

在不知道 $_SESSION['second_token'] 的情况下,无法在另一个上下文中重复使用为一个表单生成的 token 。 重要的是您使用单独的 token 作为 HMAC key ,而不是您刚刚放在页面上的那个。

奖励:混合方法 + Twig 集成

任何使用 Twig templating engine 的人通过将此过滤器添加到他们的 Twig 环境中,可以从简化的双重策略中受益:

$twigEnv->addFunction(
new \Twig_SimpleFunction(
'form_token',
function($lock_to = null) {
if (empty($_SESSION['token'])) {
$_SESSION['token'] = bin2hex(random_bytes(32));
}
if (empty($_SESSION['token2'])) {
$_SESSION['token2'] = random_bytes(32);
}
if (empty($lock_to)) {
return $_SESSION['token'];
}
return hash_hmac('sha256', $lock_to, $_SESSION['token2']);
}
)
);

使用这个 Twig 函数,您可以像这样使用这两种通用标记:

<input type="hidden" name="token" value="{{ form_token() }}" />

或锁定变体:

<input type="hidden" name="token" value="{{ form_token('/my_form.php') }}" />

Twig 只关心模板渲染;您仍然必须正确验证 token 。在我看来,Twig 策略提供了更大的灵 active 和简单性,同时保持了最大安全性的可能性。


一次性 CSRF token

如果您有一个安全要求,即每个 CSRF token 只能使用一次,那么最简单的策略是在每次成功验证后重新生成它。但是,这样做会使之前的每一个 token 都失效,这与同时浏览多个标签的人不能很好地混合。

Paragon Initiative Enterprises 维护着 Anti-CSRF library对于这些极端情况。它仅适用于一次性使用的 per-form token 。当 session 数据中存储了足够的 token 时(默认配置:65535),它将首先循环出最旧的未兑换 token 。

关于php - 如何使用 PHP 正确添加跨站请求伪造 (CSRF) token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6287903/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com