การจัดการช่องโหว่ Host Header Attack (Reset Poisoning)
- หน้าเว็บนี้คือส่วนของระบบ “Reset Password” โดย Business Function หลักคือการให้ผู้ใช้งานกรอกอีเมลเพื่อขอเปลี่ยนรหัสผ่านลับ (Secret) เมื่อกดปุ่ม “Reset” ระบบจะทำการส่งอีเมลที่มีลิงก์สำหรับตั้งรหัสผ่านใหม่ไปให้ผู้ใช้ตามอีเมลที่ระบุ

2.การทดสอบ และช่องโหว่
- หน้าเว็บนี้มีช่องโหว่ที่เรียกว่า Host Header Attack (Reset Poisoning) ซึ่งเกิดจากการที่ระบบนำค่าจาก HTTP Host Header ที่ส่งมาจากเบราว์เซอร์ของผู้ใช้มาสร้างเป็น URL ในอีเมลโดยตรง
- การทดสอบ: ผู้โจมตีสามารถปลอมแปลง Host Header ใน Request ให้เป็นเซิร์ฟเวอร์ของตนเอง (เช่น attacker.com) เมื่อระบบส่งเมลออกไป ลิงก์รีเซ็ตรหัสผ่านจะชี้ไปที่เซิร์ฟเวอร์ของผู้โจมตี ทำให้ผู้โจมตีสามารถดักจับ Token ลับของเหยื่อได้ทันที
- ขั้นตอนที่ 1: การดักจับ Request (Intercept)
-
กรอกอีเมลเหยื่อ (เช่น alice@alice.com) แล้วกดปุ่ม Reset host ต้องขึ้น
host 192.168.1.111

- เครื่องมือที่เราจำลองเป็นผู้โจตี

- ขั้นตอนที่ 2: การปลอมแปลงโดเมน (Host Manipulation)
- ผู้โจมตี จะทำการแก้ไขบรรทัด Host: จากเดิมที่เป็น IP ของแล็บ (เช่น 192.168.1.111) ให้กลายเป็นโดเมนของผู้โจมตี เช่น attacker-domain.com เราใช้ mod headers จำลองเป็นผู้โจมตี

POST /bWAPP/hostheader_2.php HTTP/1.1 Host: attacker-domain.com <-- (จุดที่แก้ไข) Content-Type: application/x-www-form-urlencoded ... email=bee@bee.pwn&action=reset- ขั้นตอนที่ 3: ผลลัพธ์การโจมตี (Attack Result)
- เมื่อกดปล่อย (Forward) Request ที่แก้แล้วไปที่ Server เหยื่อจะได้รับอีเมลที่มีลิงก์รีเซ็ตที่อันตราย เช่น
http://attacker-domain.com/bWAPP/secret_change.php?...
- เมื่อกดปล่อย (Forward) Request ที่แก้แล้วไปที่ Server เหยื่อจะได้รับอีเมลที่มีลิงก์รีเซ็ตที่อันตราย เช่น
3.การตรวจสอบด้วยเครื่องมือ (RIPS Scan)
- เมื่อนำไฟล์ /var/www/html/bWAPP/hostheader_2.php ไปทำการสแกนด้วยเครื่องมือ RIPS ผลการวิเคราะห์ยืนยันว่าพบช่องโหว่ร้ายแรงจริงๆ ได้แก่
- Protocol Injection: 1 จุด / Session Fixation: 1 จุด ในไฟล์ selections.php (ที่ถูกเรียกใช้)

4. ปัญหา
- ช่องโหว่ Session Fixation นอกจากปัญหาเรื่องการส่งเมลแล้ว RIPS ยังตรวจพบช่องโหว่ด้านการจัดการเซสชัน (Session Management) ในบรรทัดที่ 78 ของไฟล์ selections.php
- ลักษณะของปัญหา (Vulnerability Concept) จุดที่เกิดปัญหา (Sensitive Sink): การเรียกใช้ฟังก์ชัน
setcookie() - สาเหตุ: ระบบมีการนำค่าจาก
$_POST['security_level']มาสร้างเป็น Cookie โดยตรง ซึ่งในบางกรณีหากระบบยอมรับค่า Session ID จากตัวแปรที่ผู้ใช้ส่งมา (Source) จะทำให้เกิดช่องโหว่นี้ได้ - เพิ่มเติม ผู้โจมตีสามารถ “กำหนด” หรือ “บังคับ” (Fixate) ให้เหยื่อใช้ Session ID ที่ผู้โจมตีทราบค่าอยู่แล้ว เมื่อเหยื่อทำการ Login สำเร็จ ผู้โจมตีก็จะสามารถใช้ Session ID เดียวกันนั้นสวมรอยเข้าสู่บัญชีของเหยื่อได้ทันที

5.แนวทางการแก้ไขและป้องกัน (The Patch)
- การแก้ไขที่ดีต้องทำในระดับโครงสร้างเพื่อป้องกันช่องโหว่หลายประเภทพร้อมกัน
- Output Encoding: การใช้ htmlspecialchars() จะช่วยแปลงตัวอักษรพิเศษอย่าง < > “ ‘ & ให้กลายเป็น HTML entities (เช่น
<หรือ") ซึ่งช่วยป้องกันทั้ง Cross-Site Scripting (XSS) และการแทรกคำสั่งแปลกปลอมในโปรโตคอลอีเมลครับ - Defense in Depth: นอกจากการใช้ฟังก์ชันกรองข้อมูลแล้ว แนวทางที่ดีที่สุดสำหรับหน้า Reset Password คือการ ห้ามใช้ค่าจาก Header แต่ให้ใช้ค่าโดเมนที่ระบบกำหนดไว้เอง (Static/Hardcoded) ในทุกระดับความปลอดภัย เพื่อตัดโอกาสการโจมตีจากฝั่งผู้ใช้อย่างถาวร
- Output Encoding: การใช้ htmlspecialchars() จะช่วยแปลงตัวอักษรพิเศษอย่าง < > “ ‘ & ให้กลายเป็น HTML entities (เช่น
6.แก้ไขช่องโหว่
- ทำการแก้ไขในไฟล์ selections.php ที่ path: /var/www/html/bWAPP/
- เปลี่ยนมาใช้ตัวแปรพักค่า ($input_value) แล้วใช้ switch กำหนดค่าให้ตัวแปรใหม่ ($level_final) แทน การทำแบบนี้ทำให้ RIPS มั่นใจว่าค่าที่จะถูกเอาไปใช้ เป็นค่าที่เรากำหนดเอง (0, 1, 2) ไม่ใช่ค่าแปลกปลอมจากภายนอก
- เพิ่มคำสั่ง session_regenerate_id(true);
- ในคำสั่ง setcookie(…) เราเปลี่ยนพารามิเตอร์ตัวสุดท้ายจาก false เป็น true

7.ทดสอบหลังการแก้ไข (Security Test) และทดสอบ business function
- ทำการสแกนซ้ำ จพพบว่าเหลือช่องโหว่แค่ 1 ตัว จากนั้นเราไปทดสอบส่ง e-mail อีกครั้ง

- เรามาทดสอบหน้าหน้าเว็บนี้มีช่องโหว่ที่เรียกว่า Host Header Attack (Reset Poisoning) อีกรอบ
- กรอกอีเมลalice@alice.com แล้วกดปุ่ม Reset
- ปรากกฎว่า ยังเป็น Host: attacker-domain.com ไม่ตองตกใจเพราะเราแก้ไขช่องโหว่ไปแล้ว

- เช็คที่ บที่แท็บ Cookies พบว่าคุกกี้ security_level ถูกบันทึกค่าที่ถูกต้องตามที่ระบบกำหนดไว้ (เช่น 0, 1, 2) และมีการเปลี่ยนรหัสเซสชันใหม่ด้วยคำสั่ง session_regenerate_id(true) ทำให้ผู้โจมตีไม่สามารถสวมรอยเซสชันเดิมได้

สรุป
การแก้โค้ด เพื่อปิดช่องโหว่ ได้อย่างสมบูรณ์ โดยที่ระบบยังคงให้บริการรีเซ็ตรหัสผ่านและเปลี่ยนระดับความปลอดภัยได้ตาม Business Function เดิม