简体   繁体   English

CSRF保护在手机上失败

[英]CSRF protection failing on mobiles

within index.php, I have placed this at the top 在index.php中,我将其放在顶部

<?php
session_start();

function generate_secure_token($length = 16)
{
    return bin2hex(openssl_random_pseudo_bytes($length));
}

$_SESSION['csrf_token'] = generate_secure_token();
$token = $_SESSION['csrf_token'];

?>

Within my form I then have a hidden field 在我的表单中,然后有一个隐藏字段

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

Within my Javascript I make an Ajax request 在我的Javascript中,我发出Ajax请求

submitHandler: function(form) {
    $.ajax({
        type: "POST",
        url: "php/process.php",
        dataType: "json",
        data: {
            'csrf_token': $("#csrf_token").val()
        }
    }).done(function(response) {
        if (response === 'success') {
            window.location.replace("thanks.php");
        }
    }).fail(function(jqXHR, textStatus) {
        return false;
    });
}

And then finally within process.php I check the CSRF 最后在process.php中,我检查了CSRF

<?php
session_start();

$errors = array();
$userData = array();

if (!isset($_POST['csrf_token']) ||
    empty($_POST['csrf_token']) ||
    $_POST['csrf_token'] != $_SESSION['csrf_token']) {
    $errors['csrf_token'] = 'Something went wrong';
}

if (!empty($errors)) {
    echo json_encode('failure');
    sendErrorEmail($errors, "Validation", $userData, __LINE__);
} else {
    //Do something
}

I have noticed that I am getting a lot of error emails relating to the CSRF token not being set. 我注意到我收到许多与CSRF令牌未设置有关的错误电子邮件。 Within sendErrorEmail I am sending myself the browser information for those that fail, and I have noticed that 90% of them are IPhone or Android. sendErrorEmail我向自己发送了失败消息的浏览器信息,并且我注意到其中90%是iPhone或Android。

Is there anything specific to this code that may not work within smart phones? 此代码是否有某些特定内容可能无法在智能手机中使用?

Thanks 谢谢

You are regenerating the CSRF token on every request to index.php , so if a user opens something up in a new window/tab after visiting the form page, their token won't validate when they try to submit the form, which would explain why the results you are seeing are also inconsistent. 您将在对index.php每次请求中重新生成CSRF令牌,因此,如果用户在访问表单页面后在新窗口/选项卡中打开了某些内容,则当他们尝试提交表单时,其令牌将不会生效。为什么您看到的结果也不一致。 I suggest instead making the CSRF token last for the user's entire session: 我建议改为使CSRF令牌在用户的整个会话中都处于持续状态:

<?php
session_start();

function generate_secure_token($length = 16)
{
    if (!isset($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(openssl_random_pseudo_bytes($length));
    }
}

generate_secure_token();

The point of using CSRF tokens is to prevent a remote website from causing a currently logged in user from executing unwanted actions on your website. 使用CSRF令牌的目的是防止远程网站导致当前登录的用户对您的网站执行不需要的操作。 In order to execute the action, a token is required, and this token is only supplied by your web application. 为了执行操作,需要一个令牌,并且该令牌仅由您的Web应用程序提供。 If the token is pseudo-randomly generated (as in your case), guessing it is already essentially impossible, so regenerating the token on each request does not add much to the overall security, unless your app has some sort of other vulnerability (eg XSS) that could then cause the token to be leaked back to the malicious website. 如果令牌是伪随机生成的(如您的情况),则猜测它已经基本上是不可能的,因此,除非您的应用程序存在某种其他漏洞(例如XSS),否则在每个请求上重新生成令牌不会增加整体安全性),然后可能导致令牌泄漏回恶意网站。

See also: New CSRF token per request or NOT? 另请参阅: 每个请求是否有新的CSRF令牌?

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

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