본문으로 건너뛰기

เนื้อหาภาษาไทย / 태국어 콘텐츠

시스템 가이드 검수 완료된 콘텐츠

การตรวจสอบ CSRF Token เมื่อรับ Form

บทความนี้อธิบายวิธีการตรวจสอบ CSRF Token ที่ส่งมาจาก Form เพื่อยืนยันความถูกต้องของคำขอ โดยเปรียบเทียบ Token ที่ได้รับกับ Token ที่เก็บไว้ใน Session และลบ Token...

การตรวจสอบ CSRF Token เมื่อรับ Form

ในบทที่แล้ว เราได้เรียนรู้วิธีการสร้าง Form พร้อม CSRF Token เพื่อป้องกันการโจมตีแบบ Cross-Site Request Forgery (CSRF) ในบทนี้ เราจะมาดูวิธีการตรวจสอบ CSRF Token ที่เราได้รับจาก Form เมื่อผู้ใช้ส่งข้อมูล เพื่อให้แน่ใจว่าคำขอ (request) นั้นมาจาก Form ของเราจริงๆ และไม่ได้ถูกปลอมแปลง

หลักการทำงาน

หลักการตรวจสอบ CSRF Token นั้นง่ายมาก เราจะเปรียบเทียบค่า CSRF Token ที่ส่งมาจาก Form กับค่า CSRF Token ที่เราเก็บไว้ใน Session หากทั้งสองค่าตรงกัน แสดงว่าคำขอนั้นน่าจะมาจาก Form ของเราจริง ๆ แต่ถ้าไม่ตรงกัน แสดงว่าอาจมีการพยายามโจมตีเกิดขึ้น เราก็จะปฏิเสธคำขอนั้น

ขั้นตอนการตรวจสอบ CSRF Token

  1. รับค่า CSRF Token จาก Form: เมื่อผู้ใช้ส่ง Form มา เราจะดึงค่า CSRF Token ที่ถูกส่งมาพร้อมกับข้อมูลอื่น ๆ
  2. ตรวจสอบว่ามี CSRF Token ใน Session หรือไม่: ตรวจสอบว่าเราได้เก็บ CSRF Token ไว้ใน Session หรือไม่ หากไม่มี แสดงว่ามีบางอย่างผิดพลาด
  3. เปรียบเทียบค่า CSRF Token: เปรียบเทียบค่า CSRF Token ที่ได้รับจาก Form กับค่าที่เก็บไว้ใน Session
  4. จัดการผลลัพธ์:
    • ถ้า Token ตรงกัน: แสดงว่าคำขอนั้นถูกต้อง เราสามารถดำเนินการกับข้อมูลที่ได้รับได้
    • ถ้า Token ไม่ตรงกัน: แสดงว่าอาจมีการโจมตี เราควรปฏิเสธคำขอและอาจแสดงข้อความผิดพลาดให้ผู้ใช้ทราบ
  5. ลบ CSRF Token จาก Session: หลังจากตรวจสอบ Token แล้ว เราควรลบ Token นั้นออกจาก Session เพื่อป้องกันการ Replay Attack (การนำ Token เดิมกลับมาใช้ซ้ำ)

ตัวอย่างโค้ด PHP

สมมติว่าเรามี Form ที่ส่งข้อมูลไปยังไฟล์ process_form.php และเราได้สร้าง CSRF Token ในบทที่แล้ว ตอนนี้เราจะมาดูโค้ด process_form.php ที่ใช้ตรวจสอบ CSRF Token กัน

<?php

session_start();

// ฟังก์ชันสำหรับตรวจสอบ CSRF Token
function validateCSRFToken($tokenName, $tokenValue) {
  if (!isset($_SESSION[$tokenName])) {
    return false; // ไม่พบ Token ใน Session
  }

  if ($_SESSION[$tokenName] !== $tokenValue) {
    return false; // Token ไม่ตรงกัน
  }

  // ลบ Token หลังจากใช้งาน
  unset($_SESSION[$tokenName]);

  return true; // Token ถูกต้อง
}

// ตรวจสอบว่ามีการส่ง Form มาหรือไม่
if ($_SERVER["REQUEST_METHOD"] == "POST") {
  // ตรวจสอบว่ามี CSRF Token ถูกส่งมาหรือไม่
  if (isset($_POST['csrf_token'])) {
    $csrfTokenValue = $_POST['csrf_token'];

    // ตรวจสอบ CSRF Token
    if (validateCSRFToken('csrf_token', $csrfTokenValue)) {
      // CSRF Token ถูกต้อง ดำเนินการกับข้อมูลที่ได้รับ
      echo "<p>CSRF Token ถูกต้อง!</p>";

      // ดึงข้อมูลจาก Form
      $username = $_POST['username'];
      $password = $_POST['password'];

      // แสดงข้อมูล
      echo "<p>Username: " . htmlspecialchars($username) . "</p>";
      echo "<p>Password: " . htmlspecialchars($password) . "</p>";

      // **สำคัญ:** ในสถานการณ์จริง ควรตรวจสอบและทำความสะอาดข้อมูลเพิ่มเติม
      // ก่อนที่จะนำไปใช้งานหรือบันทึกลงฐานข้อมูล

    } else {
      // CSRF Token ไม่ถูกต้อง
      echo "<p style='color: red;'>CSRF Token ไม่ถูกต้อง! คำขอถูกปฏิเสธ.</p>";
    }
  } else {
    // ไม่มี CSRF Token ถูกส่งมา
    echo "<p style='color: red;'>ไม่มี CSRF Token ถูกส่งมา!</p>";
  }
} else {
  // ไม่ได้ส่ง Form มา
  echo "<p style='color: red;'>วิธีการส่งคำขอไม่ถูกต้อง!</p>";
}

?>

คำอธิบายโค้ด:

  • session_start();: เริ่มต้น Session เพื่อให้เราสามารถเข้าถึงข้อมูลที่เก็บไว้ใน Session ได้
  • validateCSRFToken($tokenName, $tokenValue): ฟังก์ชันนี้ใช้สำหรับตรวจสอบ CSRF Token โดย:
    • ตรวจสอบว่ามี Token ชื่อ $tokenName ใน Session หรือไม่
    • เปรียบเทียบค่า Token ที่ส่งมา ($tokenValue) กับค่าที่เก็บไว้ใน Session
    • ถ้า Token ตรงกัน จะลบ Token นั้นออกจาก Session ด้วย unset($_SESSION[$tokenName]); เพื่อป้องกันการ Replay Attack
    • คืนค่า true ถ้า Token ถูกต้อง และ false ถ้าไม่ถูกต้อง
  • $_SERVER["REQUEST_METHOD"] == "POST": ตรวจสอบว่าคำขอถูกส่งมาด้วยวิธีการ POST หรือไม่
  • isset($_POST['csrf_token']): ตรวจสอบว่ามี CSRF Token ถูกส่งมาพร้อมกับ Form หรือไม่
  • $_POST['csrf_token']: ดึงค่า CSRF Token ที่ส่งมาจาก Form
  • validateCSRFToken('csrf_token', $csrfTokenValue): เรียกใช้ฟังก์ชัน validateCSRFToken() เพื่อตรวจสอบ Token
  • ถ้า Token ถูกต้อง เราจะดึงข้อมูลอื่น ๆ จาก Form (ในตัวอย่างนี้คือ username และ password) และแสดงผล
  • ถ้า Token ไม่ถูกต้อง เราจะแสดงข้อความผิดพลาด

ตัวอย่าง Form (form.html)

เพื่อให้เห็นภาพรวม เราจะแสดงตัวอย่าง Form ที่ส่งข้อมูลไปยัง process_form.php อีกครั้ง

<?php
session_start();

// สร้าง CSRF Token
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

$csrfToken = $_SESSION['csrf_token'];
?>

<form action="process_form.php" method="post">
  <label for="username">Username:</label><br>
  <input type="text" id="username" name="username"><br><br>

  <label for="password">Password:</label><br>
  <input type="password" id="password" name="password"><br><br>

  <input type="hidden" name="csrf_token" value="<?php echo $csrfToken; ?>">

  <input type="submit" value="Submit">
</form>

ข้อควรระวัง

  • อย่าลืมเริ่มต้น Session: ต้องเริ่มต้น Session ด้วย session_start() ก่อนที่จะเข้าถึงหรือแก้ไขข้อมูลใน Session
  • ตรวจสอบและทำความสะอาดข้อมูล: หลังจากตรวจสอบ CSRF Token แล้ว ควรตรวจสอบและทำความสะอาดข้อมูลอื่น ๆ ที่ได้รับจาก Form ก่อนที่จะนำไปใช้งานหรือบันทึกลงฐานข้อมูล เพื่อป้องกันการโจมตีอื่น ๆ เช่น SQL Injection หรือ XSS
  • ใช้ฟังก์ชัน htmlspecialchars(): เมื่อแสดงข้อมูลที่ได้รับจากผู้ใช้ ควรใช้ฟังก์ชัน htmlspecialchars() เพื่อป้องกัน XSS
  • จัดการ Error อย่างเหมาะสม: ควรจัดการ Error ที่อาจเกิดขึ้นระหว่างการตรวจสอบ CSRF Token อย่างเหมาะสม เช่น แสดงข้อความผิดพลาดที่เป็นมิตรต่อผู้ใช้

สรุป

การตรวจสอบ CSRF Token เป็นขั้นตอนสำคัญในการป้องกันการโจมตีแบบ CSRF การเปรียบเทียบ Token ที่ได้รับจาก Form กับ Token ที่เก็บไว้ใน Session ช่วยให้เรามั่นใจได้ว่าคำขอนั้นมาจาก Form ของเราจริง ๆ และไม่ได้ถูกปลอมแปลง อย่าลืมลบ Token ออกจาก Session หลังจากใช้งานเพื่อป้องกันการ Replay Attack และตรวจสอบให้แน่ใจว่าคุณได้ตรวจสอบและทำความสะอาดข้อมูลอื่น ๆ ที่ได้รับจาก Form อย่างเหมาะสม

Office.in.th Custom Service

이 구조를 바탕으로 시스템을 개발하거나 맞춤 변경하고 싶으신가요?

Office.in.th는 엔터프라이즈 웹 애플리케이션, API 연동, 공공/민간 업무 관리 시스템을 설계·개발하며 장기 지원을 제공합니다.

소프트웨어 개발 서비스 보기