【问题标题】:Issues while implementing a PHP session token实现 PHP 会话令牌时的问题
【发布时间】:2019-02-04 11:25:43
【问题描述】:

我正在尝试对网络表单实施 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";
}
?>

我在 index.html 中的 jQuery 尝试

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

如果上面的 PHP 没有错误,我曾认为成功将其转换为 index.php 可以解决我的问题,但我很难这样做。

【问题讨论】:

  • 可以分享整个index.html文件内容吗?
  • 顺便说一句,你应该在token.php中回显token变量,否则该文件没有任何内容并且ajax响应没有内容。
  • 将 index.html 转换为 index.php 会加载正文空白”通常意味着 .php 解析失败(致命的不可恢复)。您的浏览器应该显示服务器 500 错误?检查服务器上的错误日志(如果您启用了日志记录)。
  • 您遇到的问题是 $.get('token.php'); 在服务器返回数据后不会对数据执行任何操作。大概您想将该脚本的输出写回您的页面?
  • @Alberto Boss 不允许我识别该网站,因此我无法在不删除大部分内容的情况下发布索引。我是否需要获取生成的令牌并将其设置为隐藏字段,以便我可以在 formsubmit.php 中进行比较?

标签: php html session token csrf-protection


【解决方案1】:

您的代码存在一些问题:

token.php需要输出token。就像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 的响应写回页面。这可以通过我上面的回答来解决。

【讨论】:

  • 感谢您的 cmets。当我在浏览器中导航到 php 文件时,我能够毫无问题地访问和运行它们。 403 和 500 错误似乎是由我的编码技巧引起的。我明天将解决令牌问题,感谢您提供的修改。至于 iFrame,我愚蠢地认为我可以让它在 HTML 中运行 php。
  • 您可以让 PHP 脚本在 iframe 中执行,但这不是实现您在此处尝试执行的任何操作的正确方法。如上所述,使用 jquery 将token.php 的输出写回您的网页。这里根本不需要 iframe。
猜你喜欢
  • 1970-01-01
  • 2014-01-23
  • 2017-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多