Проблемы при реализации токена сеанса PHP

Я пытаюсь внедрить защиту CSRF в веб-форму. Это одностраничный веб-сайт, который собирает данные, отправляет их в файл PHP, который затем отправляет мне информацию по электронной почте. Веб-страница функционирует по назначению (за вычетом безопасности).

У меня есть следующие проблемы:

  1. Я не могу понять, как реализовать код PHP для установки токена; преобразование index.html в index.php загружает пустое тело. Я думаю, что решение этого, вероятно, решит мои проблемы.
  2. Когда я пытаюсь вызвать token.php из jQuery, я получаю ошибку 403.
  3. Когда я пытаюсь запустить скрипт в 1-пиксельном iframe, я получаю ошибку 500 (я предполагаю, что он запускается в HTML).

токен.php

<?php
session_start();

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

$token = $_SESSION['token'];
?>

formsubmit.php

<?php 
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    if (!empty($_POST['token'])) {
        if (hash_equals($_SESSION['token'], $_POST['token'])) {
            $emailbody = 'Name: ' . $_POST['m_title'] . ' ' . $_POST['m_firstname'] . ' ' . $_POST['m_surname'] . "\n"
                . 'Email: ' . $_POST['m_email'] . "\n"
                . 'Phone: ' . $_POST['m_phone'] . "\n"
                . 'D.O.B: ' . $_POST['m_dob_day'] . ' ' . $_POST['m_dob_month'] . ' ' . $_POST['m_dob_year'] . "\n"         
                . 'Postcode: ' . $_POST['m_postcode'] . "\n"
                . 'Lenders: ' . $_POST['m_bank1']  . ',' . $_POST['m_bank2'] . ',' . $_POST['m_bank3'] . ',' . $_POST['m_bank4'] . ',' . $_POST['m_bank5'] . ',' . $_POST['m_bank6'] . ',' . $_POST['m_bank7'] . ',' . $_POST['m_bank8'];               
            mail('**removed**', 'Web Lead', $emailbody);
            header('Location: **removed**/thankyou');
            exit();
        }   
        else {
            echo "token invalid";
        }
    }
    else {
        echo "token blank";
    }
}
else {
    echo "invalid request";
}
?>

Моя попытка jQuery в index.html

<script>
$(document).ready(function() {
    $.get('token.php');
}); 
</script>

При условии, что приведенный выше PHP не пронизан ошибками, я предполагал, что успешное преобразование его в index.php решит мои проблемы, но у меня возникли трудности с этим.


person Niall    schedule 29.08.2018    source источник
comment
Можете ли вы поделиться всем содержимым файла index.html?   -  person Alberto    schedule 29.08.2018
comment
Кстати, вы должны повторить переменную token в token.php, иначе из этого файла ничего не выйдет, и ответ ajax не будет иметь содержимого.   -  person Alberto    schedule 29.08.2018
comment
преобразование index.html в index.php загружает пустое тело обычно означает, что синтаксический анализ .php остановлен (фатально неисправим). Ваш браузер должен показывать ошибку сервера 500? Проверьте журналы ошибок на вашем сервере (если у вас включено ведение журнала).   -  person IncredibleHat    schedule 29.08.2018
comment
Проблема, с которой вы столкнулись, заключается в том, что $.get('token.php'); ничего не делает с данными после их возврата сервером. Предположительно, вы хотите записать вывод этого скрипта обратно на свою страницу?   -  person Andy    schedule 29.08.2018
comment
@Alberto Boss не позволяет мне идентифицировать веб-сайт, поэтому я не могу опубликовать индекс, не удалив из него большие куски. Нужно ли мне взять сгенерированный токен и установить его в скрытое поле, чтобы я мог сравнить его в formsubmit.php?   -  person Niall    schedule 29.08.2018
comment
@IncredibleHat Теперь они есть, я сообщу, как только немного повозлюсь.   -  person Niall    schedule 29.08.2018
comment
@Andy Это я просто пытался запустить скрипт. Я считаю, что мне нужно установить токен в качестве переменной для публикации с формой, чтобы я мог сравнить его на formsubmit.php Это правильно?   -  person Niall    schedule 29.08.2018
comment
@ Найл, я отправил ответ. Проверьте это и прокомментируйте, если это работает/не работает.   -  person Andy    schedule 29.08.2018


Ответы (1)


Есть несколько проблем с вашим кодом:

token.php необходимо вывести токен. Что так же просто, как echo $token;

Основная проблема в том, что вы использовали следующий jquery:

$(document).ready(function() {
$.get('token.php');
});

Это означает, что когда страница (index.html) загружается, ваш браузер отправляет ajax-запрос к token.php. Однако... дальше ничего не происходит. На самом деле вы ничего не делаете с ответом (выводом) от token.php.

Что вам нужно сделать, так это поместить ответ от token.php на свою веб-страницу. Исходя из кода, который вы разместили, я предполагаю, что есть поле формы с именем "token"? Если это так, то вы должны сделать такой запрос ajax, который записывает ответ token.php в это поле:

$(document).ready(function() {
    $.get('token.php').done(function(data) {
        $('input[name="token"]').val(data);
    }).fail() {
       // Handle ajax request failure here
    });
)};

Чтобы ответить на ваши вопросы:

  1. $_SESSION['token'] = bin2hex(random_bytes(32)); означает, что переменная $_SESSION['token'] содержит ваш токен. Вот где вы его устанавливаете.

  2. Если вы получаете ошибку 403, запрашивающую token.php в запросе ajax, это означает, что сервер не будет обрабатывать этот запрос. Так что это может быть проблема с разрешениями или какая-то другая проблема. Попробуйте поместить die('test'); в первую строку скрипта, а затем выполнить /token.php в браузере. Вы можете получить к нему доступ, или он выдает вам ошибку? Если он доступен, он скажет «тест». Проверьте журнал ошибок сервера, если вы не уверены, почему не можете получить к нему доступ. Судя по коду, маловероятно, что URL-адрес скрипта неверный или это приведет к ошибке 404.

  3. Непонятно, почему вы беспокоитесь о: "Когда я пытаюсь запустить скрипт в 1-пиксельном iframe". Я предполагаю, что это попытка записать ответ token.php обратно на страницу. Это можно решить с помощью моего ответа выше.

person Andy    schedule 29.08.2018
comment
Спасибо за ваши комментарии. Я могу без проблем получать доступ к php-файлам и запускать их, когда я перехожу к ним в браузере. Ошибки 403 и 500, похоже, вызваны моими навыками кодирования. Я рассмотрю проблему с токеном завтра, спасибо за предоставленные вами поправки. Что касается iFrame, я был глуп, думая, что смогу заставить его запускать php в HTML. - person Niall; 29.08.2018
comment
Вы можете заставить PHP-скрипт выполняться внутри iframe, но это неправильный способ добиться всего, что вы пытаетесь сделать здесь. Используйте jquery, чтобы записать вывод token.php обратно на вашу веб-страницу, как описано выше. Здесь вообще не нужны фреймы. - person Andy; 30.08.2018