【问题标题】:CSRF session tokenCSRF 会话令牌
【发布时间】:2014-09-09 22:17:01
【问题描述】:

我正在尝试在表单上实现一个简单的 CSRF 保护,但我做错了。如果有人能指出我做错了什么,我将不胜感激。

错误:每次提交表单时,我都会收到“Invalid Submission2”,因为令牌更改(在提交表单后),因为是在同一页面上生成的?

编辑——我忘了​​提,另一个文件 (config.php) 已经有 session_start()。

<?php
class Module_Post extends Base_Module {

    public function start()
    {
        requireLogin();

        if (isset($_GET['act'])) {
            switch($_GET['act']) {
                case 'text':
                    $this->text();
                    break;
                case 'image':
                    $this->image();
                    break;
                default:
                    $this->text();
                    break;
            }
        } else {
            $this->text();
        }
    }

    private function text()
    {

        // Generate random unique token to prevent cross-site request forgery (CSRF).
        if(empty($_SESSION['form_token'])) 
        {
            $form_token = md5(uniqid(rand(), TRUE));
            $_SESSION['form_token'] = $form_token;
        }

        if(isset($_POST['submit'])) 
        {
            // Clean the content from cross-site scripting (xss)
            $content = trim($_POST['content']);
            $content = Xss::clean($content);

            // Validate that the form token
            if(!isset($_POST['form_token'], $_SESSION['form_token'])) {
                $err = 'Invalid Submission';
            } elseif ($_POST['form_token'] != $_SESSION['form_token']) {
                $err = 'Invalid Submission2';
            } elseif (strlen($content) < 10) {
                $err = 'Your content contains too few characters.';
            }

            if(isset($err)) {
                unset( $_SESSION['form_token']);
                $this->setMessage($err, 'FAIL');
                header('Location: index.php?mod=post');
                exit;
            }


            // Insert database data here, then redirect

            $this->setMessage('Your post was published successfully.', 'GOOD');
            header('Location: index.php');
            exit;
        }

        $this->tpl->assign('form_token', $form_token);
        $this->tpl->display('new/text.tpl');
    }

}
?>

HTML(text.tpl 文件)

<form method='post' enctype='multipart/form-data' action='#'>
  <fieldset>
    <textarea rows="8" id="new_post" name="content" class="input-block-level"></textarea>
    <input type="hidden" name="form_token" value="{$form_token}" />
    <button type="submit" name="submit" class="btn btn-info pull-left">Create Post</button>
  </fieldset>
</form>

【问题讨论】:

  • 你已经开始了会话,所以你的会话读/写工作了吗?检查隐藏元素中是否也确实有一个标记。
  • 是的,我忘了说,我已经添加了 session_start();另一个文件(config.php)中的其他地方。表格显示令牌。我认为问题在于令牌是在同一页面中生成的,一旦提交表单,就会生成另一个令牌并正在检查旧令牌..嗯。

标签: php smarty


【解决方案1】:

你需要改变这一行

$this->tpl->assign('form_token', $form_token);

进入:

$this->tpl->assign('form_token', $_SESSION['form_token']);

那是因为你只在这个条件下生成你的令牌:

if(empty($_SESSION['form_token'])) 
{
    $form_token = md5(uniqid(rand(), TRUE));
    $_SESSION['form_token'] = $form_token;
}

并使用此条件取消设置:

if(isset($err)) {
    unset( $_SESSION['form_token']);
}

因此,如果您发送一次表单然后重新加载页面(不提交表单只是 url),$form_token 变量是未知的,因为 $_SESSION['form_token'] 不为空,然后在您的表单中您有空令牌。

如果您在 PHP 中打开了显示错误,您会在这种情况下在 PHP 中看到:

Undefined variable: form_token in 

【讨论】:

    猜你喜欢
    • 2020-02-10
    • 2023-01-24
    • 2012-09-01
    • 2021-10-23
    • 1970-01-01
    • 2019-02-27
    • 2018-07-12
    • 2014-01-23
    • 2021-11-23
    相关资源
    最近更新 更多