实施PHP会话令牌时出现的问题

时间:2018-08-29 15:41:54

标签: php html session token csrf-protection

我正在尝试对Web表单实施CSRF保护。它是一个一页的网站,可捕获数据,将其发布到PHP文件,然后通过电子邮件将信息发送给我。该网页可以正常运行(不包括安全性)。

我遇到以下问题:

  1. 我不知道如何实现PHP代码来设置令牌;将index.html转换为index.php将加载空白正文。我认为解决此问题可能会解决我的问题。
  2. 当我尝试从jQuery调用token.php时,出现403错误。
  3. 当我尝试在1像素iframe中运行脚本时,出现500错误(我认为是在HTML上运行)。

token.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可以解决我的问题,但是这样做很难。

1 个答案:

答案 0 :(得分:0)

您的代码有一些问题:

token.php需要输出令牌。就像echo $token;

一样简单

主要问题是您使用了以下jquery:

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

这意味着加载页面(index.html)时,浏览器向token.php发出ajax请求。但是...没有其他事情发生。您实际上对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. 如果在ajax请求中请求token.php时出现403错误,则意味着服务器将不会处理该请求。因此这可能是权限问题或其他问题。尝试将die('test');放在脚本的第一行,然后在浏览器中执行/token.php。您可以访问它,还是给您一个错误?如果可以访问,它将说“测试”。如果不确定为什么无法访问它,请检查服务器错误日志。根据代码,脚本的URL不太可能是错误的,否则不会出现 404 错误。

  3. 目前尚不清楚您为什么要打扰:“当我尝试在1像素iframe中运行脚本时” 。我假设这是尝试将token.php的响应写回到页面。这可以通过我上面的答案来解决。