การสร้าง Form พร้อม CSRF Token
ในบทที่แล้ว เราได้เรียนรู้เกี่ยวกับ CSRF (Cross-Site Request Forgery) และความสำคัญของการป้องกัน วันนี้เราจะมาดูวิธีการสร้างฟอร์มที่มี CSRF token เพื่อป้องกันการโจมตีประเภทนี้
หลักการทำงาน
หลักการคือ เราจะสร้าง token ที่ไม่ซ้ำกันสำหรับแต่ละ session และเก็บ token นี้ไว้ใน session จากนั้นเราจะแทรก token นี้ลงในฟอร์มที่ผู้ใช้เห็น เมื่อผู้ใช้ส่งฟอร์ม เราจะตรวจสอบว่า token ที่ส่งมาตรงกับ token ที่เก็บไว้ใน session หรือไม่ ถ้าไม่ตรง แสดงว่าอาจมีการโจมตี CSRF
ขั้นตอนการสร้าง Form พร้อม CSRF Token
- สร้าง Hidden Field: สร้าง input field ที่มี type เป็น "hidden" เพื่อเก็บ CSRF token
- เก็บ Token ใน Session: สร้างและเก็บ CSRF token ไว้ใน $_SESSION
- ส่ง Token ไปพร้อมกับ Form: แทรก CSRF token ลงใน hidden field ของฟอร์ม
ตัวอย่างโค้ด
1. สร้างฟังก์ชันสำหรับสร้าง CSRF Token:
<?php
session_start(); // เริ่มต้น session (ถ้ายังไม่ได้เริ่ม)
function generateCSRFToken() {
// สร้าง token ที่คาดเดาได้ยาก
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $token;
return $token;
}
// สร้าง token หากยังไม่มีใน session
if (!isset($_SESSION['csrf_token'])) {
generateCSRFToken();
}
$csrf_token = $_SESSION['csrf_token'];
?>
คำอธิบาย:
session_start(): เริ่มต้น session เพื่อให้เราสามารถใช้$_SESSIONได้ หากคุณเริ่มต้น session ไว้แล้วในไฟล์อื่น ไม่จำเป็นต้องเรียกใช้อีกครั้งgenerateCSRFToken(): ฟังก์ชันนี้สร้าง token โดยใช้random_bytes(32)ซึ่งสร้าง string สุ่ม 32 ไบต์ จากนั้นเราแปลงเป็น hexadecimal string ด้วยbin2hex()ทำให้ token มีความยาว 64 ตัวอักษร$_SESSION['csrf_token'] = $token;: เก็บ token ที่สร้างขึ้นไว้ใน session เพื่อใช้ตรวจสอบในภายหลังif (!isset($_SESSION['csrf_token'])): ตรวจสอบว่ามี token ใน session อยู่แล้วหรือไม่ ถ้ายังไม่มี ก็จะสร้าง token ใหม่$csrf_token = $_SESSION['csrf_token'];: ดึงค่า token จาก session มาเก็บไว้ในตัวแปร$csrf_tokenเพื่อนำไปใช้ในฟอร์ม
2. สร้าง Form พร้อม Hidden Field ที่มี 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 htmlspecialchars($csrf_token); ?>">
<input type="submit" value="Submit">
</form>
คำอธิบาย:
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrf_token); ?>">: นี่คือ hidden field ที่เราใส่ CSRF token ลงไปname="csrf_token": กำหนดชื่อของ field เป็นcsrf_tokenเพื่อให้เราสามารถเข้าถึงค่านี้ได้ในไฟล์process_form.phpvalue="<?php echo htmlspecialchars($csrf_token); ?>": กำหนดค่าของ field เป็น CSRF token ที่เราสร้างไว้ก่อนหน้านี้htmlspecialchars()ใช้เพื่อป้องกัน XSS โดยการแปลงอักขระพิเศษให้เป็น HTML entities
ข้อควรระวัง
- การใช้
htmlspecialchars(): สำคัญมากที่จะต้องใช้htmlspecialchars()เมื่อแสดงค่า$csrf_tokenใน HTML เพื่อป้องกัน XSS - การ regenerate token: บางครั้งคุณอาจต้องการ regenerate token หลังจากที่ผู้ใช้ส่งฟอร์มสำเร็จแล้ว เพื่อป้องกันการ reuse token
- Session Timeout: ตรวจสอบให้แน่ใจว่า session timeout เหมาะสม หาก session หมดอายุ CSRF token ก็จะหายไปด้วย
สรุป
ในบทนี้ เราได้เรียนรู้วิธีการสร้างฟอร์มที่มี CSRF token ซึ่งเป็นขั้นตอนสำคัญในการป้องกันการโจมตี CSRF ในบทต่อไป เราจะมาดูวิธีการตรวจสอบ CSRF token เมื่อผู้ใช้ส่งฟอร์ม