内部 $_SERVER["REQUEST_METHOD"] 表单的 CSRF
CSRF for internal $_SERVER["REQUEST_METHOD"] form
有史以来第一次尝试实施 CSRF 令牌...
我有一个内部 $_SERVER["REQUEST_METHOD"]
表格 ...
大多数在线讨论都是通过 _$POST
php 表格完成的...
所以...阅读完所有内容后,我认为既然我在内部部分拥有它,我应该在那里设置令牌...
所以这就是我所做的......但显然我在这里误解了一些东西因为它不起作用......不仅仅是误解......我也不确定我应该做什么.. .所以...如果你能解释我应该做什么,这样我就可以正确设置它...我真的很感激
<?php
session_start(); //allows use of session variables
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["first-name"])) {
$firstNameErr = "First name is required";
} else {
$first_name = test_input($_POST["first-name"]);
}
if (empty($_POST["last-name"])) {
$lastNameErr = "Last name is required";
} else {
$last_name = test_input($_POST["last-name"]);
}
if (empty($_POST["email"])) {
$emailErr = "Email is required";
} else {
$email = test_input($_POST["email"]);
}
if (empty($_POST["message"])) {
$messageErr = "Message is required";
} else {
$message = test_input($_POST["message"]);
}
if(isset($first_name) && isset($last_name) && isset($email) && isset($message) && isset($token))
{
$_SESSION['first_name'] = $first_name;
$_SESSION['last_name'] = $last_name;
$_SESSION['email'] = $email;
$_SESSION['message'] = $message;
$_SESSION['token'] = $token;
header("Location: SessionsCRSF.php");
}
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
在同一页上是表格(放置一个片段,但你明白了):
<form class="ui form" method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
<input type="hidden" name="token" value="<?php echo $token; ?>" />
<div class="field">
<label>First Name</label>
<input name="first-name" id="first-name" placeholder="First Name" type="text" value="<?php if(isset($first_name)) { echo $first_name; }?>">
<?php if(isset($firstNameErr)) print ('<span class="error">* ' . $firstNameErr . '</span>'); ?>
</div>
(...)
</form>
但我不知道如何通过您在 header 中看到的 SessionsCRSF.php
表格进行测试 ...
这是 SessionsCRSF.php
表单的片段,因为其余部分只是 PHPMailer 内容:
<?php
session_start();
if ($_POST['token'] == $_SESSION['token'])
{
die('working, yay?');
}
$first_name = $_SESSION['first-name'];
$last_name = $_SESSION['last-name'];
$email = $_SESSION['email'];
$message = nl2br($_SESSION['message']);
require 'PHPMailerAutoload.php';
$mail = new PHPMailer;
已编辑
好的,所以 .. 这就是我目前有效的方法:
<?php
session_start(); //allows use of session variables
if ($_SERVER["REQUEST_METHOD"] == "POST" && $_SESSION['token'] == $_POST['token'] && !empty($_SESSION['token'])) {
if (empty($_POST["first-name"])) {
$firstNameErr = "First name is required";
} else {
$first_name = test_input($_POST["first-name"]);
}
if (empty($_POST["last-name"])) {
$lastNameErr = "Last name is required";
} else {
$last_name = test_input($_POST["last-name"]);
}
if (empty($_POST["email"])) {
$emailErr = "Email is required";
} else {
$email = test_input($_POST["email"]);
}
if (empty($_POST["message"])) {
$messageErr = "Message is required";
} else {
$message = test_input($_POST["message"]);
}
if(isset($first_name) && isset($last_name) && isset($email) && isset($message))
{
$_SESSION['first_name'] = $first_name;
$_SESSION['last_name'] = $last_name;
$_SESSION['email'] = $email;
$_SESSION['message'] = $message;
header("Location: contact9SessionsCRSF2.php");
exit;
}
}
else {
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
您有您的页面,其中包含您的 $_SESSION
值,并且您在 HTML 表单的隐藏字段中具有相同值的 INPUT 值。
Page 1:
[SESSION] ... [INPUT]
然后您将表单提交到目标地址,此处为第 2 页,然后检查您提交的隐藏字段值是否等于 $_SESSION
值,该值未由输入表单字段传递。
此输入值是从 $_POST
数组中找到的。
Page 2:
[SESSION] ... [POST]
特别针对您的问题,您将表单提交到 PHP_SELF
页面(通常 PHP_SELF
是一个不好的变量,不鼓励使用),这是同一页面。但是,您的数据检查是在 sessionCRSF.php
页面上完成的,因此您应该做的是更新您的表单以输入:
<form action='sessionCRSF.php' ... >
然后在该页面的顶部,您对令牌值的检查应该会成功。
您似乎对 SERVER 请求方法有些困惑,有 GET/POST/PUT 和其他方法,如果您有
I have an internal $_SERVER["REQUEST_METHOD"] form
这究竟是什么?如果它是一个表单,那么它就是一个 GET/POST 方法,据我所知,这不是内部的 - 即使它在同一台服务器上,它也是从一个页面到另一个页面,所以上面的概念适用。
解决方案
通过讨论和澄清,我现在可以看到解决方案:
在处理表单提交的 If
语句中,您没有任何对令牌发布值的处理,$_POST['token']
。因此,您需要添加一条语句来处理该问题,以最简单的形式,在为 $_SESSION
表单数据设置值的代码处,添加一行:
$_SESSION['posted_token'] = $_POST['token'];
这就是您所需要的,然后在 sessionCRSF.php
中比较这两个值,这样您就可以得到:
if ($_SESSION['posted_token'] == $_SESSION['token'])
{
die('working, yay?');
}
(你早些时候让我对 "internal" 表格等感到困惑!)
编辑:
您需要在生成表单时设置原始 $_SESSION['token']
,在提交表单时 NOT,您的代码当前创建 $_SESSION['token']
值在每次迭代中,因为页面自身引用它意味着标记值——随机的——永远不会相同。您需要设置
if (form submitted){
save submitted POSTED token
}
else{
/// form not submitted
generate a token and save to session
}
不要在同一次迭代中做这两件事!!
代码
因为有时候只是看到它更容易....
代码已更新以在 POST 提交时比较令牌,因此绕过了将数据发送到另一个页面进行比较的整个需要。
<?php
session_start(); //allows use of session variables
if ($_SERVER["REQUEST_METHOD"] == "POST" &&
$_SESSION['token'] == $_POST['token'] && !empty($_SESSION['token'])) {
if (empty($_POST["first-name"])) {
$firstNameErr = "First name is required";
} else {
$first_name = test_input($_POST["first-name"]);
}
...etc...
if(isset($first_name) && isset($last_name) && isset($email) && isset($message))
{
$_SESSION['first_name'] = $first_name;
$_SESSION['last_name'] = $last_name;
$_SESSION['email'] = $email;
$_SESSION['message'] = $message;
header("Location: SessionsCRSF.php");
exit; //ALWAYS end execution after sending location headers.
}
}
else {
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
}
有史以来第一次尝试实施 CSRF 令牌...
我有一个内部 $_SERVER["REQUEST_METHOD"]
表格 ...
大多数在线讨论都是通过 _$POST
php 表格完成的...
所以...阅读完所有内容后,我认为既然我在内部部分拥有它,我应该在那里设置令牌...
所以这就是我所做的......但显然我在这里误解了一些东西因为它不起作用......不仅仅是误解......我也不确定我应该做什么.. .所以...如果你能解释我应该做什么,这样我就可以正确设置它...我真的很感激
<?php
session_start(); //allows use of session variables
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["first-name"])) {
$firstNameErr = "First name is required";
} else {
$first_name = test_input($_POST["first-name"]);
}
if (empty($_POST["last-name"])) {
$lastNameErr = "Last name is required";
} else {
$last_name = test_input($_POST["last-name"]);
}
if (empty($_POST["email"])) {
$emailErr = "Email is required";
} else {
$email = test_input($_POST["email"]);
}
if (empty($_POST["message"])) {
$messageErr = "Message is required";
} else {
$message = test_input($_POST["message"]);
}
if(isset($first_name) && isset($last_name) && isset($email) && isset($message) && isset($token))
{
$_SESSION['first_name'] = $first_name;
$_SESSION['last_name'] = $last_name;
$_SESSION['email'] = $email;
$_SESSION['message'] = $message;
$_SESSION['token'] = $token;
header("Location: SessionsCRSF.php");
}
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
在同一页上是表格(放置一个片段,但你明白了):
<form class="ui form" method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
<input type="hidden" name="token" value="<?php echo $token; ?>" />
<div class="field">
<label>First Name</label>
<input name="first-name" id="first-name" placeholder="First Name" type="text" value="<?php if(isset($first_name)) { echo $first_name; }?>">
<?php if(isset($firstNameErr)) print ('<span class="error">* ' . $firstNameErr . '</span>'); ?>
</div>
(...)
</form>
但我不知道如何通过您在 header 中看到的 SessionsCRSF.php
表格进行测试 ...
这是 SessionsCRSF.php
表单的片段,因为其余部分只是 PHPMailer 内容:
<?php
session_start();
if ($_POST['token'] == $_SESSION['token'])
{
die('working, yay?');
}
$first_name = $_SESSION['first-name'];
$last_name = $_SESSION['last-name'];
$email = $_SESSION['email'];
$message = nl2br($_SESSION['message']);
require 'PHPMailerAutoload.php';
$mail = new PHPMailer;
已编辑
好的,所以 .. 这就是我目前有效的方法:
<?php
session_start(); //allows use of session variables
if ($_SERVER["REQUEST_METHOD"] == "POST" && $_SESSION['token'] == $_POST['token'] && !empty($_SESSION['token'])) {
if (empty($_POST["first-name"])) {
$firstNameErr = "First name is required";
} else {
$first_name = test_input($_POST["first-name"]);
}
if (empty($_POST["last-name"])) {
$lastNameErr = "Last name is required";
} else {
$last_name = test_input($_POST["last-name"]);
}
if (empty($_POST["email"])) {
$emailErr = "Email is required";
} else {
$email = test_input($_POST["email"]);
}
if (empty($_POST["message"])) {
$messageErr = "Message is required";
} else {
$message = test_input($_POST["message"]);
}
if(isset($first_name) && isset($last_name) && isset($email) && isset($message))
{
$_SESSION['first_name'] = $first_name;
$_SESSION['last_name'] = $last_name;
$_SESSION['email'] = $email;
$_SESSION['message'] = $message;
header("Location: contact9SessionsCRSF2.php");
exit;
}
}
else {
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
您有您的页面,其中包含您的 $_SESSION
值,并且您在 HTML 表单的隐藏字段中具有相同值的 INPUT 值。
Page 1:
[SESSION] ... [INPUT]
然后您将表单提交到目标地址,此处为第 2 页,然后检查您提交的隐藏字段值是否等于 $_SESSION
值,该值未由输入表单字段传递。
此输入值是从 $_POST
数组中找到的。
Page 2:
[SESSION] ... [POST]
特别针对您的问题,您将表单提交到 PHP_SELF
页面(通常 PHP_SELF
是一个不好的变量,不鼓励使用),这是同一页面。但是,您的数据检查是在 sessionCRSF.php
页面上完成的,因此您应该做的是更新您的表单以输入:
<form action='sessionCRSF.php' ... >
然后在该页面的顶部,您对令牌值的检查应该会成功。
您似乎对 SERVER 请求方法有些困惑,有 GET/POST/PUT 和其他方法,如果您有
I have an internal $_SERVER["REQUEST_METHOD"] form
这究竟是什么?如果它是一个表单,那么它就是一个 GET/POST 方法,据我所知,这不是内部的 - 即使它在同一台服务器上,它也是从一个页面到另一个页面,所以上面的概念适用。
解决方案
通过讨论和澄清,我现在可以看到解决方案:
在处理表单提交的 If
语句中,您没有任何对令牌发布值的处理,$_POST['token']
。因此,您需要添加一条语句来处理该问题,以最简单的形式,在为 $_SESSION
表单数据设置值的代码处,添加一行:
$_SESSION['posted_token'] = $_POST['token'];
这就是您所需要的,然后在 sessionCRSF.php
中比较这两个值,这样您就可以得到:
if ($_SESSION['posted_token'] == $_SESSION['token'])
{
die('working, yay?');
}
(你早些时候让我对 "internal" 表格等感到困惑!)
编辑:
您需要在生成表单时设置原始 $_SESSION['token']
,在提交表单时 NOT,您的代码当前创建 $_SESSION['token']
值在每次迭代中,因为页面自身引用它意味着标记值——随机的——永远不会相同。您需要设置
if (form submitted){
save submitted POSTED token
}
else{
/// form not submitted
generate a token and save to session
}
不要在同一次迭代中做这两件事!!
代码
因为有时候只是看到它更容易....
代码已更新以在 POST 提交时比较令牌,因此绕过了将数据发送到另一个页面进行比较的整个需要。
<?php
session_start(); //allows use of session variables
if ($_SERVER["REQUEST_METHOD"] == "POST" &&
$_SESSION['token'] == $_POST['token'] && !empty($_SESSION['token'])) {
if (empty($_POST["first-name"])) {
$firstNameErr = "First name is required";
} else {
$first_name = test_input($_POST["first-name"]);
}
...etc...
if(isset($first_name) && isset($last_name) && isset($email) && isset($message))
{
$_SESSION['first_name'] = $first_name;
$_SESSION['last_name'] = $last_name;
$_SESSION['email'] = $email;
$_SESSION['message'] = $message;
header("Location: SessionsCRSF.php");
exit; //ALWAYS end execution after sending location headers.
}
}
else {
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
}