我正在寻找一种方法将CSRF令牌添加到我正在创建的应用程序中。需要注意的是,该应用程序目前不使用Cookie或会话。在PHP中没有Cookie的CSRF令牌
我很想找到一种方法来引入CSRF令牌,而无需:
- 在我的应用介绍状态。
- 使用会话cookie的或(
$_SESSION
/$_COOKIE
)存储
这是在所有的可能性,还是我停留在我的应用程序创建新的状态。
我正在寻找一种方法将CSRF令牌添加到我正在创建的应用程序中。需要注意的是,该应用程序目前不使用Cookie或会话。在PHP中没有Cookie的CSRF令牌
我很想找到一种方法来引入CSRF令牌,而无需:
$_SESSION
/$_COOKIE
)存储这是在所有的可能性,还是我停留在我的应用程序创建新的状态。
你可以,但它不会很安全。
下面是一个例子但不使用这一点,它可能是一个好主意:
// Do this somewhere
define('CSRF_SALT', '4dedMj4CWgBMNhRsoTpJlokwB5wTz7UsmF8Mq4uzFIbv');
$token = base64_encode(
hash_hmac(
'sha256',
date('Ymd') . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'],
CSRF_SALT,
true
)
);
if (\hash_equals($_POST['security_token'], $token)) {
// Form passes validation
}
的缺点是,这些标记是固有可重复使用的,因此,如果一个泄漏,攻击者可以简单地重复使用(或重新计算)它。您也可以尝试在散列计算中添加表单action =“”的值。
function getToken($action)
{
return base64_encode(
hash_hmac(
'sha256',
hash_hmac(
'sha256',
date('Ymd') . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'],
hash('sha256', $action, true),
true
),
CSRF_SALT,
true
)
);
}
echo "<form action='register.php' method='post'>\n";
echo "<input type='hidden' name='security_token' value='".getToken('register.php')."' />\n";
// ...
无论如何,你对会话有什么诅咒?
我不喜欢会话的原因是因为它需要服务器端存储。我工作在一个开源库,这意味着有更多的东西需要记录,理想情况下,我还需要提供一种方法使其在多个负载平衡的服务器上工作。 – Evert 2015-02-27 18:07:16
我认识到memcache支持的会话存储可以帮助解决这个问题......但我必须解释的越少越好。很好的答案,但最终我决定只使用一个cookie(但没有会话)。 – Evert 2015-02-27 18:07:57
https://resonantcore.net/blog/2015/02/modern-defense-against-csrf-attacks - 如果你使用composer,你可以使用resonancecore/anti-csrf作为依赖。 – 2015-02-28 05:17:26
您可以使用轻量级数据库并存储令牌以及ip地址,用户代理,到期时间和请求的url,或者您可以尝试使用数据库和会话存储来存储创建令牌的密钥。例如。
$post = array();
If (isset($_POST) && !empty($_POST)) {
If (isset($_POST['csrftoken']) && isset($_SESSION['csrfkey'])) {
// check if csrftoken exists in db and fetch the row
$hash = hash('sha256', $row['String'] . $_SESSION['csrfKey']);
// delete the db record
If ($hash === $_POST['csrfToken']) {
$post = (array) $_POST;
// check if expiry time has not passed
// check requested url
// check user agent and ip adres
}
}
$_REQUEST = null;
$_POST = null;
}
If (!isset($_SESSION['csrfKey'])) {
$_SESSION['csrfKey'] = uniqid('key_', true);
}
$string = uniqid('token_', true);
$token = hash('sha256', $string . $_SESSION['csrfKey']);
// save token and string along with expirytime in db
echo "<input type='hidden' name='csrftoken' value='" . $token . "' />";
嵌入像一个轻量级JWT到窗体,并检查它在服务器上,提供为准断言你要检查 - 通常你会添加当前时间标记,这样就可以到期令牌。
的基本程序是:
如果没有服务器端存储的概念,令牌如何是好的? – 2015-02-23 17:12:51
CSRF令牌*的种类是*状态验证。 “无状态CSRF令牌”是无意义的。 – 2015-02-23 17:13:28
你提出的任何解决方案都不使用cookie或服务器端状态可能会挫败CSRF令牌的目的 – meagar 2015-02-23 17:14:56