簡體   English   中英

內部$ _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>

但是我不知道如何通過標題中列出的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值,並且您的INPUT值在HTML表單的隱藏字段中具有相同的值。

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和其他方法,如果您有一個

我有一個內部的$ _SERVER [“ REQUEST_METHOD”]表單

這到底是什么? 據我所知,如果是表單,則它是GET / POST方法,並且不是內部的-即使它在同一服務器上,也從一頁到另一頁,因此適用上述概念。

通過討論和澄清,我現在可以看到解決方案:

在處理表單提交的If語句中,您沒有對令牌發布值$_POST['token']進行任何處理。 因此,您需要添加一條語句以最簡單的形式在設置$_SESSION表單數據的值的代碼點處添加一行:

$_SESSION['posted_token'] = $_POST['token'];

這就是您所需要的,然后在sessionCRSF.php比較這兩個值,然后得到:

 if ($_SESSION['posted_token'] == $_SESSION['token'])
    {
      die('working, yay?'); 
    }

(您之前讓我對“內部”表格等感到困惑!)

編輯:

您需要在生成表單時設置原始的$_SESSION['token'] ,而不是在提交表單時設置,當前您的代碼在每次迭代時都會創建$_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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM