เจาะลึก Stored XSS: เมื่อ Markdown และ JSONP กลายเป็นช่องทางสู่การขโมยคุกกี้แอดมิน

เจาะลึก Stored XSS: เมื่อ Markdown และ JSONP กลายเป็นช่องทางสู่การขโมยคุกกี้แอดมิน

ในโลกออนไลน์ที่เต็มไปด้วยการโจมตีทางไซเบอร์ การทำความเข้าใจช่องโหว่ต่าง ๆ ถือเป็นสิ่งสำคัญสำหรับทั้งนักพัฒนาและผู้ใช้งานทั่วไป ช่องโหว่ Cross-Site Scripting (XSS) เป็นหนึ่งในภัยคุกคามที่พบได้บ่อยและอันตราย โดยเฉพาะอย่างยิ่ง Stored XSS ที่สามารถฝังโค้ดอันตรายลงในเซิร์ฟเวอร์ และโจมตีผู้ที่เข้ามาเยี่ยมชมเว็บไซต์ทุกคน

บทความนี้จะพาไปเจาะลึกถึงการรวมกันของช่องโหว่หลายจุด ทั้งการใช้งาน Markdown ที่ไม่รัดกุม, การใช้ประโยชน์จาก JSONP, และการหลบเลี่ยง Content Security Policy (CSP) จนสามารถนำไปสู่การขโมยคุกกี้ของผู้ดูแลระบบได้

Stored XSS: ภัยเงียบที่ฝังลึก

XSS คืออะไร และ Stored XSS ร้ายกาจแค่ไหน

XSS ย่อมาจาก Cross-Site Scripting คือช่องโหว่ที่ทำให้ผู้โจมตีสามารถฉีดโค้ดฝั่งไคลเอ็นต์ (Client-side script) ซึ่งส่วนใหญ่เป็น JavaScript เข้าไปในหน้าเว็บเพจได้

โดยทั่วไป XSS แบ่งออกเป็นหลายประเภท แต่ Stored XSS ถือเป็นประเภทที่ร้ายแรงเป็นพิเศษ

โค้ดอันตรายจะถูกบันทึกไว้ในฐานข้อมูลของเว็บไซต์ และเมื่อผู้ใช้งานคนอื่นเปิดหน้าเว็บเพจที่มีโค้ดนั้นฝังอยู่ โค้ดก็จะถูกรันในเบราว์เซอร์ของผู้ใช้งานทันทีโดยไม่รู้ตัว

ผลกระทบที่เกิดขึ้นมีตั้งแต่การขโมยข้อมูลสำคัญ เช่น คุกกี้เซสชัน (session cookies) ที่ใช้ในการยืนยันตัวตน, การเปลี่ยนเนื้อหาของหน้าเว็บ หรือแม้แต่การเปลี่ยนเส้นทางไปยังเว็บไซต์ปลอม

JSONP: ประตูหลังที่อาจถูกเปิดทิ้งไว้

ทำความเข้าใจ JSONP และความเสี่ยง

JSONP (JSON with Padding) เป็นเทคนิคที่เคยนิยมใช้สำหรับการดึงข้อมูลข้ามโดเมน (cross-domain data) ในยุคก่อนที่ CORS (Cross-Origin Resource Sharing) จะถูกนำมาใช้อย่างแพร่หลาย

หลักการทำงานคือ การใช้แท็ก <script> เพื่อโหลดข้อมูลจากโดเมนอื่น เนื่องจากแท็ก <script> ไม่มีข้อจำกัดเรื่อง Cross-Origin

ข้อมูลที่ส่งกลับมาจะถูกห่อหุ้มด้วยการเรียกใช้ฟังก์ชัน Callback ที่กำหนดไว้ล่วงหน้า เช่น callbackFunction({"key": "value"})

ความเสี่ยงของ JSONP เกิดขึ้นเมื่อปลายทางที่ให้บริการ JSONP ไม่ได้ตรวจสอบอินพุตอย่างรอบคอบ หรือยอมให้ผู้โจมตีควบคุมส่วนหนึ่งของโค้ดที่จะถูกรัน เช่น ชื่อฟังก์ชัน Callback ซึ่งอาจนำไปสู่การรันโค้ด JavaScript ที่ไม่พึงประสงค์ได้

CSP Bypass: กำแพงป้องกันที่ถูกเจาะ

CSP คืออะไร และทำไมถึงสำคัญ

Content Security Policy (CSP) คือนโยบายความปลอดภัยเนื้อหาที่เว็บไซต์กำหนดขึ้นเพื่อลดความเสี่ยงจากการโจมตีประเภท XSS และการฉีดโค้ดอื่น ๆ

CSP ทำหน้าที่เป็นเหมือนกำแพงป้องกัน โดยกำหนดว่าทรัพยากรประเภทใด (เช่น สคริปต์, รูปภาพ, สไตล์ชีต) สามารถโหลดจากแหล่งที่มาใดได้บ้าง

การใช้ CSP ที่แข็งแกร่งจะช่วยให้เบราว์เซอร์บล็อกการโหลดสคริปต์ที่ไม่ได้รับอนุญาต ทำให้ผู้โจมตีไม่สามารถรันโค้ด XSS ได้ง่าย ๆ

เมื่อ CSP มีช่องโหว่: การใช้ JSONP เป็นทางผ่าน

แม้ CSP จะเป็นเครื่องมือป้องกันที่มีประสิทธิภาพ แต่ก็ยังสามารถถูกหลบเลี่ยงได้ โดยเฉพาะอย่างยิ่งหากนโยบาย CSP อนุญาตให้โหลดสคริปต์จากโดเมนที่ถูกเชื่อถือ หรือจากโดเมนของตัวเอง

หากโดเมนที่ได้รับอนุญาตจาก CSP มีบริการ JSONP ที่มีช่องโหว่ ผู้โจมตีสามารถใช้บริการ JSONP นั้นเป็นช่องทางในการฉีดโค้ด JavaScript ที่ต้องการได้

โดยการสร้าง Payload ที่เรียกใช้ JSONP endpoint พร้อมกำหนดชื่อฟังก์ชัน Callback เป็นโค้ด JavaScript ที่เป็นอันตราย

เมื่อหน้าเว็บถูกโหลดและมีการเรียกใช้ JSONP เบราว์เซอร์จะรันโค้ดที่ผู้โจมตีแทรกเข้าไปผ่านฟังก์ชัน Callback นั้น

จุดเริ่มต้นของปัญหา: Markdown และ DOMPurify ที่เข้าใจผิด

Markdown ที่เป็นพิษ

ระบบที่อนุญาตให้ผู้ใช้งานใส่เนื้อหาในรูปแบบ Markdown มักจะทำการแปลง Markdown ให้เป็น HTML เพื่อแสดงผล

หากกระบวนการแปลงนี้ไม่รัดกุม และไม่ทำการ Sanitization (การล้างข้อมูล) ที่เพียงพอ ผู้โจมตีสามารถแทรก HTML หรือ JavaScript ที่เป็นอันตรายผ่าน Markdown ได้

ตัวอย่างเช่น การใช้ลิงก์ Markdown ที่มี javascript: scheme ([Click Me](javascript:alert(1))) หรือการแทรกแท็ก HTML โดยตรงที่ตัวแปลง Markdown อนุญาต

เมื่อ DOMPurify ไม่ได้ช่วยทั้งหมด

DOMPurify เป็นไลบรารีที่ยอดเยี่ยมสำหรับการล้าง HTML เพื่อให้ปลอดภัยจาก XSS

แต่ถึงแม้จะมี DOMPurify การตั้งค่าที่ไม่ถูกต้อง หรือการทำงานร่วมกันกับส่วนอื่น ๆ ของระบบก็อาจสร้างช่องโหว่ได้

ในบางกรณี DOMPurify อาจถูกตั้งค่าให้ยอมรับแท็กหรือ attribute บางอย่างที่ดูเหมือนไม่เป็นอันตราย แต่เมื่อรวมเข้ากับการโจมตีแบบ JSONP และการหลบเลี่ยง CSP กลับกลายเป็นช่องทางให้ผู้โจมตีสามารถฉีดสคริปต์ที่เป็นอันตรายได้สำเร็จ

เส้นทางสู่การขโมยคุกกี้

การผสานรวมช่องโหว่เพื่อเป้าหมาย

การโจมตีครั้งนี้เป็นการผสานรวมช่องโหว่หลายจุดเข้าด้วยกันอย่างแยบยล เริ่มจากการใช้ช่องโหว่ Stored XSS ผ่านอินพุต Markdown เพื่อฝัง Payload ที่เป็นอันตรายลงในระบบ

Payload ดังกล่าวจะใช้ประโยชน์จาก JSONP endpoint ที่ถูกระบุว่า “เชื่อถือได้” ในนโยบาย CSP

เมื่อผู้ดูแลระบบเข้าชมหน้าที่มี Payload นี้ โค้ด JavaScript ที่ซ่อนอยู่จะถูกรัน เบราว์เซอร์จะทำการเรียก JSONP endpoint และเนื่องจากผู้โจมตีสามารถควบคุมฟังก์ชัน Callback ได้ จึงสามารถแทรกโค้ดที่ขโมยคุกกี้ของผู้ดูแลระบบส่งไปยังเซิร์ฟเวอร์ของผู้โจมตีได้สำเร็จ

ซึ่งหมายถึงการเข้าควบคุมบัญชีของผู้ดูแลระบบได้อย่างสมบูรณ์

บทเรียนและความระมัดระวัง

เหตุการณ์นี้แสดงให้เห็นถึงความซับซ้อนของช่องโหว่ด้านความปลอดภัยในปัจจุบัน ที่มักเกิดจากการรวมกันของหลายปัจจัย ไม่ใช่เพียงแค่ช่องโหว่เดียว

การตรวจสอบความปลอดภัยของระบบอย่างละเอียด การทำความเข้าใจถึงการทำงานของไลบรารีและเฟรมเวิร์กต่าง ๆ อย่างถ่องแท้ รวมถึงการระมัดระวังในการตั้งค่าและใช้งานฟังก์ชันต่าง ๆ เป็นสิ่งจำเป็นอย่างยิ่ง

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