Preeyanuch

Simple. Warm. Elegant.

View the Project on GitHub

รายงานการแก้ไขช่องโหว่ Cross-Site Scripting (XSS) แบบ Reflected


Business Function หน้าดังกล่าวมีวัตถุประสงค์หลักคือ: ✅ ให้ผู้ใช้กดปุ่ม “Go back” เพื่อกลับไปยังหน้าก่อนหน้า การทำงานเดิมของหน้า มีปุ่ม Go back เมื่อกดปุ่ม ระบบจะพาผู้ใช้ย้อนกลับไปยังหน้าที่เข้ามาก่อนหน้า โดยทั่วไปมักใช้คำสั่ง JavaScript เช่น history.back()หรือรับค่า URL จากพารามิเตอร์แล้ว redirect กลับ

cf


ปัญหาสำคัญคือ ค่า HTTP_REFERER เป็นข้อมูลที่สามารถถูกปลอมแปลงได้จากฝั่งผู้ใช้หรือผู้โจมตี แต่ในโค้ดนี้มีการนำค่าดังกล่าวมาใส่ในคำสั่ง JavaScript โดยตรงเพื่อใช้กำหนดปลายทางของการ redirect หากไม่มีการตรวจสอบหรือเข้ารหัสข้อมูลอย่างปลอดภัย อาจทำให้ผู้โจมตีแทรกโค้ด JavaScript อันตรายเข้ามาได้**

cf

cf


สาเหตุของปัญหา:

มีช่องโหว่ประเภท Reflected Cross-Site Scripting (XSS) อยู่ที่ส่วนปุ่ม Go Back เนื่องจากมีการนำค่าจาก $_SERVER[‘HTTP_REFERER’] ซึ่งเป็นข้อมูลที่ผู้ใช้ควบคุมได้ มาแสดงผลโดยไม่เข้ารหัส ทำให้ผู้โจมตีสามารถฝังโค้ด JavaScript ลงไปได้

cf

วิธีทดสอบ ลองแก้ไขค่า Referer (เช่น ผ่านเครื่องมือ Proxy หรือปลั๊กอินแก้ Header) แล้วใส่โค้ดทดสอบ เช่น หากหน้าเว็บแสดงผลหรือรันสคริปต์ดังกล่าว แสดงว่ามีช่องโหว่ Reflected XSS จริง หรือสามารถยืนยันได้จากผลการสแกนด้วยเครื่องมือด้านความปลอดภัยที่แจ้งเตือนตำแหน่งโค้ดที่มีความเสี่ยง. จากการทดสอบด้วยเครื่องมือสแกนช่องโหว่ เช่น RIPS พบว่าระบบมีช่องโหว่ประเภท Reflected XSS จริง โดยเครื่องมือระบุจุดที่มีการนำค่าจาก $_SERVER[‘HTTP_REFERER’] มาแสดงผลโดยไม่ผ่านการเข้ารหัส ทำให้มีความเสี่ยงต่อการฝังและรัน JavaScript


ปัญหาอยู่ที่ไฟล์

xss_back_button.php

วิธีแก้ที่ถูกต้อง

ตรวจสอบปัญหาจากผลการสแกน (RIPS)

ขั้นตอนแรกให้กดเครื่องหมายปุ่มที่บอกรายละเอียดปัญหา ว่าต้องแก้อย่างไรกับปัญหาที่พบเจอจากเครื่องมือสแกน

cf


เชื่อมต่อเข้าสู่เซิร์ฟเวอร์ด้วย WinSCP

เปิดโปรแกรม WinSCP เชื่อมต่อเข้าสู่เซิร์ฟเวอร์ เข้าไปยังโฟลเดอร์ของเว็บไซต์
ตรวจสอบไฟล์ที่ถูกแจ้งเตือนจาก RIPS
พบว่าไฟล์ที่เกี่ยวข้องคือ xss_back_button.php บรรทัดที่ถูกแจ้งเตือนไม่ได้ถูก Comment ไว้
แสดงว่าเป็นโค้ดที่ยังทำงานอยู่จริง cf


เปิดไฟล์ด้วย Visual Studio Code

เปิดไฟล์ xss_back_button.php ตรวจสอบตำแหน่งที่เกิดช่องโหว่วิเคราะห์การทำงานของโค้ด

cf


แก้ไขจุดปัญหาที่พบเจอ

แนวทางการแก้ไขคือ ไม่ควรนำค่าจาก $_SERVER[‘HTTP_REFERER’] มาแสดงผลโดยตรง เนื่องจากเป็นข้อมูลที่ผู้ใช้สามารถปลอมแปลงได้และอาจถูกใช้ฝังสคริปต์อันตรายได้ วิธีแก้ไขเบื้องต้นคือการทำ Output Encoding ก่อนแสดงผล โดยใช้ฟังก์ชัน htmlspecialchars() เพื่อเข้ารหัสอักขระพิเศษ ป้องกันการรัน JavaScript บนหน้าเว็บ

🔴 ก่อนแก้ไข

cf


🟢 หลังแก้ไข

วิธีแก้คือเช็ค document.referrer แทน document.referrer → จะมีค่าก็ต่อเมื่อผู้ใช้มาจากหน้าอื่นจริงๆ (คลิก link มา) ถ้าเปิดตรงๆ หรือ referrer ว่าง → ไป portal.php แทน

cf


การอัปโหลดไฟล์ที่แก้ไขแล้ว (แทนที่ไฟล์)

หลังจากแก้ไขปัญหาที่พบเจอแล้ว ให้เซฟและนำไฟล์ที่ถูกต้องไปวางแทนที่ไฟล์เดิมที่อยู่ในเซิร์ฟเวอร์ (ก่อนจะลบไฟล์เดิมต้องมีการ Blackup ข้อมูลจากไฟล์เดิมเก็บไว้ในอีกโฟล์เดอร์)

cf

อัปโหลดไฟล์ใหม่ที่แก้ไขแล้วแทนที่

cf


สำเร็จ!!

เมื่อแก้ไขปัญหาเสร็จแล้ว เช็ค RIPS อีกครั้ง จากเป็นหน้าตอนแรกเป็น 2 เมื่อแก้เสร็จแล้วจะขึ้นเหลือ 1

cf

ตรวจสอบ

ก่อนแก้ไข

cf

หลังแก้ไข

cf


ผลลัพธ์หลังการแก้ไข

หลังจากทำการแก้ไขโค้ดเพื่อปิดช่องโหว่ Reflected XSS แล้ว ได้ทำการทดสอบการทำงานของระบบอีกครั้ง โดยทดลองกรอก Domain Name เพื่อให้ระบบทำการ DNS Lookup ผลการทดสอบพบว่า ระบบยังสามารถแปลง Domain เป็น IP Address ได้ตามปกติ และปุ่ม “Go Back” ก็สามารถใช้งานได้ตามเดิม แสดงให้เห็นว่าการแก้ไขโดยการทำ Output Encoding หรือการปรับลิงก์ให้ปลอดภัยนั้น ไม่ได้กระทบต่อ Business Function หลักของระบบ ซึ่งก็คือการทำ DNS Lookup ดังนั้น แนวทางการแก้ไขนี้ถือว่าเหมาะสม เพราะสามารถปิดช่องโหว่ด้านความปลอดภัยได้ โดยไม่ส่งผลกระทบต่อการทำงานเดิมของระบบ.