Сбой защиты CSRF на мобильных телефонах - PullRequest
0 голосов
/ 07 ноября 2018

в 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'];

?>

В моей форме у меня есть скрытое поле

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

В моем 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;
    });
}

И, наконец, в 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
}

Я заметил, что получаю много сообщений об ошибках, связанных с тем, что токен CSRF не установлен. В sendErrorEmail я отправляю себе информацию из браузера для тех, кто терпит неудачу, и я заметил, что 90% из них - это IPhone или Android.

Есть ли что-то конкретное для этого кода, которое может не работать в смартфонах?

Спасибо

1 Ответ

0 голосов
/ 07 ноября 2018

Вы регенерируете токен CSRF при каждом запросе до index.php, поэтому, если пользователь открывает что-то в новом окне / вкладке после посещения страницы формы, его токен не будет проверяться при попытке отправить форму, что объясняет, почему результаты, которые вы видите, также противоречивы. Вместо этого я предлагаю сделать токен 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();

Смысл использования токенов CSRF состоит в том, чтобы не дать удаленному веб-сайту заставить не авторизованных пользователей выполнять нежелательные действия на вашем веб-сайте. Для выполнения действия требуется токен, который предоставляется только вашим веб-приложением. Если токен генерируется псевдослучайно (как в вашем случае), угадать его уже практически невозможно, поэтому восстановление токена при каждом запросе не сильно увеличивает общую безопасность, если ваше приложение не имеет какой-либо другой уязвимости (например, XSS). ), что может привести к утечке токена на вредоносный веб-сайт.

См. Также: Новый токен CSRF на запрос или НЕТ?

...