[{"data":1,"prerenderedAt":710},["ShallowReactive",2],{"post-xml-external-entity":3},{"id":4,"title":5,"body":6,"description":696,"extension":697,"meta":698,"navigation":305,"path":706,"seo":707,"stem":708,"__hash__":709,"dateDisplay":704,"image":705,"tags":700,"badge":699,"readingTime":175},"posts\u002Fposts\u002FXML-External-Entity.md","XXE (XML External Entity)",{"type":7,"value":8,"toc":688},"minimark",[9,16,21,55,59,129,133,138,179,191,197,201,241,245,259,263,271,284,385,393,397,401,420,437,446,466,470,521,525,552,564,568,639,643,684],[10,11,12,15],"p",{},[13,14,5],"strong",{}," là lỗ hổng khi parser XML cho phép xử lý các entity bên ngoài — kẻ tấn công có thể lợi dụng để đọc file cục bộ, SSRF, thực hiện Remote File Inclusion, hoặc làm OOB (out-of-band) exfiltration nếu parser tải và xử lý nội dung bên ngoài.",[17,18,20],"h1",{"id":19},"_1-cơ-chế-ý-tưởng","1) Cơ chế & ý tưởng",[22,23,24,49,52],"ul",{},[25,26,27,28,32,33,36,37,40,41,44,45,48],"li",{},"XML cho phép định nghĩa ",[29,30,31],"code",{},"\u003C!DOCTYPE ...>"," và ",[29,34,35],{},"\u003C!ENTITY ...>","; nếu parser cho phép ",[29,38,39],{},"external entity"," (ví dụ ",[29,42,43],{},"\u003C!ENTITY xxe SYSTEM \"file:\u002F\u002F\u002Fetc\u002Fpasswd\">","), khi XML chứa tham chiếu ",[29,46,47],{},"&xxe;"," parser sẽ thay thế bằng nội dung file\u002FURL.",[25,50,51],{},"Vấn đề xuất phát từ parser cấu hình mặc định cho phép xử lý external entities \u002F DTD.",[25,53,54],{},"Hậu quả: lộ file nội bộ (Local File Disclosure), SSRF (server gọi URL nội bộ), blind exfil (DNS\u002FHTTP OOB), remote code execution trong một số nền tảng.",[17,56,58],{"id":57},"_2-các-dạng-xxe-phổ-biến","2) Các dạng XXE (phổ biến)",[60,61,62,72,89,99,109,119],"ol",{},[25,63,64,67],{},[13,65,66],{},"In-band (Direct) Local File Disclosure",[22,68,69],{},[25,70,71],{},"Parser đọc file cục bộ và trả nội dung trong response.",[25,73,74,77],{},[13,75,76],{},"SSRF \u002F Remote Resource Fetch",[22,78,79],{},[25,80,81,82,88],{},"External entity trỏ đến URL (",[83,84,85],"a",{"href":85,"rel":86},"http:\u002F\u002Fintranet\u002F",[87],"nofollow","...) → server request tới internal service.",[25,90,91,94],{},[13,92,93],{},"Out-of-band (OOB) Exfiltration",[22,95,96],{},[25,97,98],{},"Entity trỏ tới attacker-controlled server (DNS\u002FHTTP) để exfil dữ liệu (thường dùng khi response không hiển thị nội dung).",[25,100,101,104],{},[13,102,103],{},"Blind XXE \u002F Time-based",[22,105,106],{},[25,107,108],{},"Không có response trực tiếp; dùng side-effects hoặc timing để dò.",[25,110,111,114],{},[13,112,113],{},"Billion Laughs \u002F XML Entity Expansion (XXE variant \u002F DoS)",[22,115,116],{},[25,117,118],{},"Lợi dụng nested entities (entity expansion) để làm exhaustion memory\u002FCPU (a.k.a. XML bomb) — gây DoS.",[25,120,121,124],{},[13,122,123],{},"XXE kết hợp với SSRF\u002FSSRF to RCE",[22,125,126],{},[25,127,128],{},"Khi server có endpoint thực thi hoặc parser có lỗ hổng bổ sung.",[17,130,132],{"id":131},"_3-ví-dụ-minh-họa-an-toàn-để-hiểu-cơ-chế","3) Ví dụ minh họa (an toàn, để hiểu cơ chế)",[10,134,135],{},[13,136,137],{},"Vulnerable XML (minh hoạ concept):",[139,140,145],"pre",{"className":141,"code":142,"language":143,"meta":144,"style":144},"language-xml shiki shiki-themes github-light github-dark","\u003C?xml version=\"1.0\"?>\n\u003C!DOCTYPE data [\n  \u003C!ENTITY xxe SYSTEM \"file:\u002F\u002F\u002Fetc\u002Fpasswd\">\n]>\n\u003Cdata>&xxe;\u003C\u002Fdata>\n","xml","",[29,146,147,155,161,167,173],{"__ignoreMap":144},[148,149,152],"span",{"class":150,"line":151},"line",1,[148,153,154],{},"\u003C?xml version=\"1.0\"?>\n",[148,156,158],{"class":150,"line":157},2,[148,159,160],{},"\u003C!DOCTYPE data [\n",[148,162,164],{"class":150,"line":163},3,[148,165,166],{},"  \u003C!ENTITY xxe SYSTEM \"file:\u002F\u002F\u002Fetc\u002Fpasswd\">\n",[148,168,170],{"class":150,"line":169},4,[148,171,172],{},"]>\n",[148,174,176],{"class":150,"line":175},5,[148,177,178],{},"\u003Cdata>&xxe;\u003C\u002Fdata>\n",[22,180,181],{},[25,182,183,184,186,187,190],{},"Nếu parser xử lý external entities, ",[29,185,47],{}," sẽ được thay bằng nội dung file ",[29,188,189],{},"\u002Fetc\u002Fpasswd"," và có thể hiển thị\u002Fđược trả về trong response.",[10,192,193,196],{},[13,194,195],{},"Lưu ý:"," ví dụ trên chỉ để hiểu cơ chế — không chạy trên hệ thống thật trừ khi là lab.",[17,198,200],{"id":199},"_4-cách-kiểm-thử-dò-lab-style-an-toàn","4) Cách kiểm thử \u002F dò (lab-style, an toàn)",[22,202,203,206,228,231,234],{},[25,204,205],{},"Tìm các endpoint nhận XML (SOAP, REST endpoints accept XML, file upload, SAML, RSS\u002FATOM parsers).",[25,207,208,209,211,212],{},"Thử gửi XML có ",[29,210,31],{}," với external entity tham chiếu tới:",[22,213,214,217,225],{},[25,215,216],{},"local file (file:\u002F\u002F\u002F...),",[25,218,219,220,224],{},"internal URL (",[83,221,223],{"rel":222},[87],"http:\u002F\u002Flocalhost:port\u002F","... ),",[25,226,227],{},"attacker-controlled host (nên dùng lab server) để kiểm tra OOB.",[25,229,230],{},"Kiểm tra cả response trực tiếp (in-band) và không trực tiếp (OOB\u002FDNS).",[25,232,233],{},"Kiểm tra khả năng bị XML Entity Expansion (billion laughs) bằng payloads đơn giản (tăng kích thước tài nguyên) — xem parser có bảo vệ.",[25,235,236,237,240],{},"Dùng proxy (Burp) để mod request, và công cụ scanner nếu cần.\n",[13,238,239],{},"Quan trọng:"," test OOB chỉ với server\u002Fhost mà em kiểm soát (lab).",[17,242,244],{"id":243},"_5-detect-nhanh-triệu-chứng","5) Detect nhanh (triệu chứng)",[22,246,247,250,253,256],{},[25,248,249],{},"Response chứa dữ liệu lạ (nội dung file, nội dung từ internal service).",[25,251,252],{},"Server thực hiện requests tới internal addresses (xem logs).",[25,254,255],{},"Kết quả lỗi liên quan XML parser khi gửi DOCTYPE (có stack trace hiển thị).",[25,257,258],{},"Bất thường network traffic đến host em kiểm soát (đối với OOB tests).",[17,260,262],{"id":261},"_6-code-cách-fix-secure-parsing-các-ví-dụ-cụ-thể","6) Code — cách fix \u002F secure parsing (các ví dụ cụ thể)",[264,265,267,268],"h3",{"id":266},"java-documentbuilderfactory-sax-khuyến-nghị","Java (DocumentBuilderFactory \u002F SAX) — ",[13,269,270],{},"khuyến nghị",[10,272,273,276,277,280,281],{},[13,274,275],{},"Vulnerable pattern",": mặc định ",[29,278,279],{},"DocumentBuilderFactory"," cho phép external entities \u002F DTD trên một số cấu hình.\n",[13,282,283],{},"Secure configuration (tắt DTD & external entities):",[139,285,289],{"className":286,"code":287,"language":288,"meta":144,"style":144},"language-java shiki shiki-themes github-light github-dark","\u002F\u002F Java secure XML parsing (DOM)\nDocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\n\n\u002F\u002F Disable DTDs (do not load external DTDs)\ndbf.setFeature(\"http:\u002F\u002Fapache.org\u002Fxml\u002Ffeatures\u002Fdisallow-doctype-decl\", true);\n\n\u002F\u002F Disable external entities\ndbf.setFeature(\"http:\u002F\u002Fxml.org\u002Fsax\u002Ffeatures\u002Fexternal-general-entities\", false);\ndbf.setFeature(\"http:\u002F\u002Fxml.org\u002Fsax\u002Ffeatures\u002Fexternal-parameter-entities\", false);\n\n\u002F\u002F Disable external DTDs as well\ndbf.setFeature(\"http:\u002F\u002Fapache.org\u002Fxml\u002Ffeatures\u002Fnonvalidating\u002Fload-external-dtd\", false);\n\ndbf.setXIncludeAware(false);\ndbf.setExpandEntityReferences(false);\n\nDocumentBuilder db = dbf.newDocumentBuilder();\n","java",[29,290,291,296,301,307,312,317,322,328,334,340,345,351,357,362,368,374,379],{"__ignoreMap":144},[148,292,293],{"class":150,"line":151},[148,294,295],{},"\u002F\u002F Java secure XML parsing (DOM)\n",[148,297,298],{"class":150,"line":157},[148,299,300],{},"DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\n",[148,302,303],{"class":150,"line":163},[148,304,306],{"emptyLinePlaceholder":305},true,"\n",[148,308,309],{"class":150,"line":169},[148,310,311],{},"\u002F\u002F Disable DTDs (do not load external DTDs)\n",[148,313,314],{"class":150,"line":175},[148,315,316],{},"dbf.setFeature(\"http:\u002F\u002Fapache.org\u002Fxml\u002Ffeatures\u002Fdisallow-doctype-decl\", true);\n",[148,318,320],{"class":150,"line":319},6,[148,321,306],{"emptyLinePlaceholder":305},[148,323,325],{"class":150,"line":324},7,[148,326,327],{},"\u002F\u002F Disable external entities\n",[148,329,331],{"class":150,"line":330},8,[148,332,333],{},"dbf.setFeature(\"http:\u002F\u002Fxml.org\u002Fsax\u002Ffeatures\u002Fexternal-general-entities\", false);\n",[148,335,337],{"class":150,"line":336},9,[148,338,339],{},"dbf.setFeature(\"http:\u002F\u002Fxml.org\u002Fsax\u002Ffeatures\u002Fexternal-parameter-entities\", false);\n",[148,341,343],{"class":150,"line":342},10,[148,344,306],{"emptyLinePlaceholder":305},[148,346,348],{"class":150,"line":347},11,[148,349,350],{},"\u002F\u002F Disable external DTDs as well\n",[148,352,354],{"class":150,"line":353},12,[148,355,356],{},"dbf.setFeature(\"http:\u002F\u002Fapache.org\u002Fxml\u002Ffeatures\u002Fnonvalidating\u002Fload-external-dtd\", false);\n",[148,358,360],{"class":150,"line":359},13,[148,361,306],{"emptyLinePlaceholder":305},[148,363,365],{"class":150,"line":364},14,[148,366,367],{},"dbf.setXIncludeAware(false);\n",[148,369,371],{"class":150,"line":370},15,[148,372,373],{},"dbf.setExpandEntityReferences(false);\n",[148,375,377],{"class":150,"line":376},16,[148,378,306],{"emptyLinePlaceholder":305},[148,380,382],{"class":150,"line":381},17,[148,383,384],{},"DocumentBuilder db = dbf.newDocumentBuilder();\n",[22,386,387],{},[25,388,389,392],{},[13,390,391],{},"Giải thích ngắn:"," tắt xử lý DOCTYPE và external entities -> parser không tải file\u002FURL bên ngoài.",[264,394,396],{"id":395},"java-stax-sax-tương-tự-set-features-để-disable-external-entities","Java (StAX \u002F SAX) — tương tự: set features để disable external entities.",[264,398,400],{"id":399},"python-lxml-defusedxml","Python (lxml \u002F defusedxml)",[22,402,403,413],{},[25,404,405,408,409,412],{},[13,406,407],{},"Không dùng"," ",[29,410,411],{},"lxml.etree.fromstring"," trực tiếp trên dữ liệu không tin cậy nếu chưa cài cấu hình an toàn.",[25,414,415,416,419],{},"Use ",[29,417,418],{},"defusedxml"," library (được thiết kế phòng chống XXE\u002FDoS):",[139,421,425],{"className":422,"code":423,"language":424,"meta":144,"style":144},"language-python shiki shiki-themes github-light github-dark","from defusedxml.ElementTree import fromstring  # safe replacement\ntree = fromstring(xml_data)\n","python",[29,426,427,432],{"__ignoreMap":144},[148,428,429],{"class":150,"line":151},[148,430,431],{},"from defusedxml.ElementTree import fromstring  # safe replacement\n",[148,433,434],{"class":150,"line":157},[148,435,436],{},"tree = fromstring(xml_data)\n",[22,438,439],{},[25,440,441,442,445],{},"Hoặc với ",[29,443,444],{},"lxml"," disable DTD:",[139,447,449],{"className":422,"code":448,"language":424,"meta":144,"style":144},"from lxml import etree\nparser = etree.XMLParser(resolve_entities=False, no_network=True, dtd_validation=False)\nroot = etree.fromstring(xml_data, parser)\n",[29,450,451,456,461],{"__ignoreMap":144},[148,452,453],{"class":150,"line":151},[148,454,455],{},"from lxml import etree\n",[148,457,458],{"class":150,"line":157},[148,459,460],{},"parser = etree.XMLParser(resolve_entities=False, no_network=True, dtd_validation=False)\n",[148,462,463],{"class":150,"line":163},[148,464,465],{},"root = etree.fromstring(xml_data, parser)\n",[264,467,469],{"id":468},"net-c-xmlreadersettings",".NET (C#) — XmlReaderSettings",[139,471,475],{"className":472,"code":473,"language":474,"meta":144,"style":144},"language-csharp shiki shiki-themes github-light github-dark","var settings = new XmlReaderSettings\n{\n    DtdProcessing = DtdProcessing.Prohibit, \u002F\u002F disable DTD\n    XmlResolver = null \u002F\u002F prevents external resource resolution\n};\nusing (var reader = XmlReader.Create(stream, settings))\n{\n    var doc = XDocument.Load(reader);\n}\n","csharp",[29,476,477,482,487,492,497,502,507,511,516],{"__ignoreMap":144},[148,478,479],{"class":150,"line":151},[148,480,481],{},"var settings = new XmlReaderSettings\n",[148,483,484],{"class":150,"line":157},[148,485,486],{},"{\n",[148,488,489],{"class":150,"line":163},[148,490,491],{},"    DtdProcessing = DtdProcessing.Prohibit, \u002F\u002F disable DTD\n",[148,493,494],{"class":150,"line":169},[148,495,496],{},"    XmlResolver = null \u002F\u002F prevents external resource resolution\n",[148,498,499],{"class":150,"line":175},[148,500,501],{},"};\n",[148,503,504],{"class":150,"line":319},[148,505,506],{},"using (var reader = XmlReader.Create(stream, settings))\n",[148,508,509],{"class":150,"line":324},[148,510,486],{},[148,512,513],{"class":150,"line":330},[148,514,515],{},"    var doc = XDocument.Load(reader);\n",[148,517,518],{"class":150,"line":336},[148,519,520],{},"}\n",[264,522,524],{"id":523},"php-libxml","PHP (libxml)",[139,526,530],{"className":527,"code":528,"language":529,"meta":144,"style":144},"language-php shiki shiki-themes github-light github-dark","libxml_disable_entity_loader(true); \u002F\u002F deprecated in newer PHP versions - prefer using proper parser options\n$dom = new DOMDocument();\n$dom->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD); \u002F\u002F don't use these flags with untrusted input\n\u002F\u002F Better: avoid enabling NOENT\u002FDTDLOAD; use XMLReader and disable DTDs.\n","php",[29,531,532,537,542,547],{"__ignoreMap":144},[148,533,534],{"class":150,"line":151},[148,535,536],{},"libxml_disable_entity_loader(true); \u002F\u002F deprecated in newer PHP versions - prefer using proper parser options\n",[148,538,539],{"class":150,"line":157},[148,540,541],{},"$dom = new DOMDocument();\n",[148,543,544],{"class":150,"line":163},[148,545,546],{},"$dom->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD); \u002F\u002F don't use these flags with untrusted input\n",[148,548,549],{"class":150,"line":169},[148,550,551],{},"\u002F\u002F Better: avoid enabling NOENT\u002FDTDLOAD; use XMLReader and disable DTDs.\n",[22,553,554],{},[25,555,556,559,560,563],{},[13,557,558],{},"Ghi chú:"," vì API khác nhau theo ngôn ngữ\u002Fphiên bản; mục tiêu là ",[13,561,562],{},"khóa DTD + disable external entity resolution",".",[17,565,567],{"id":566},"_7-prevention-best-practices-checklist","7) Prevention (best practices, checklist)",[60,569,570,576,582,588,597,603,609,615,621,627,633],{},[25,571,572,575],{},[13,573,574],{},"Disable DTD processing and external entity resolution"," ở parser (primary).",[25,577,578,581],{},[13,579,580],{},"Sử dụng parser an toàn \u002F libraries chuyên dụng"," (defusedxml, secure settings).",[25,583,584,587],{},[13,585,586],{},"Nếu cần xử lý XML từ nguồn tin cậy duy nhất",", xác thực và whitelist sources; avoid processing XML from untrusted inputs.",[25,589,590,593,594,563],{},[13,591,592],{},"Không cho phép DOCTYPE trong XML nhận vào"," — reject request có ",[29,595,596],{},"\u003C!DOCTYPE",[25,598,599,602],{},[13,600,601],{},"Nếu phải xử lý SAML\u002Fthird-party XML",", dùng thư viện SAML được cấu hình an toàn và validate signatures.",[25,604,605,608],{},[13,606,607],{},"Set XmlResolver = null \u002F no_network \u002F no external DTD option"," theo ngôn ngữ.",[25,610,611,614],{},[13,612,613],{},"Apply network egress filtering \u002F outbound access restriction",": server không nên có quyền tùy ý truy cập vào internet\u002Finternal network từ process parsing XML.",[25,616,617,620],{},[13,618,619],{},"Least privilege runtime",": tách service, không cho phép đọc file nhạy cảm bằng tài khoản ứng dụng.",[25,622,623,626],{},[13,624,625],{},"Rate-limit & size limits",": giới hạn size\u002Fcomplexity của XML để tránh entity expansion DoS.",[25,628,629,632],{},[13,630,631],{},"Logging & monitoring",": detect unusual outbound requests, DTD-related payloads, parse errors.",[25,634,635,638],{},[13,636,637],{},"Defense-in-depth",": WAF rules + input validation (reject XML containing DOCTYPE if not needed).",[17,640,642],{"id":641},"_8-testing-checklist-pentest-dev-sec","8) Testing checklist (pentest \u002F dev-sec)",[22,644,647,656,666,672,678],{"className":645},[646],"contains-task-list",[25,648,651,655],{"className":649},[650],"task-list-item",[652,653],"input",{"disabled":305,"type":654},"checkbox"," Tìm endpoint nhận XML (SOAP, REST XML body, SAML, file upload).",[25,657,659,661,662,665],{"className":658},[650],[652,660],{"disabled":305,"type":654}," Thử gửi XML có ",[29,663,664],{},"\u003C!DOCTYPE [...]>"," và refer tới file:\u002F\u002F (lab) \u002F internal URL (lab) \u002F attacker OOB server (lab) — kiểm tra in-band & OOB.",[25,667,669,671],{"className":668},[650],[652,670],{"disabled":305,"type":654}," Thử entity expansion (billion laughs) để kiểm tra bảo vệ DoS.",[25,673,675,677],{"className":674},[650],[652,676],{"disabled":305,"type":654}," Kiểm tra logs \u002F network egress \u002F app behavior.",[25,679,681,683],{"className":680},[650],[652,682],{"disabled":305,"type":654}," Xác minh fixes: gửi payload cũ và confirm parser không load entities \u002F trả lỗi \u002F reject.",[685,686,687],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":144,"searchDepth":157,"depth":157,"links":689},[690,692,693,694,695],{"id":266,"depth":163,"text":691},"Java (DocumentBuilderFactory \u002F SAX) — khuyến nghị",{"id":395,"depth":163,"text":396},{"id":399,"depth":163,"text":400},{"id":468,"depth":163,"text":469},{"id":523,"depth":163,"text":524},"cách hoạt động của external entity, ví dụ in-band\u002FOOB\u002Fbillion-laughs, test lab và cách cấu hình parser an toàn (Java\u002FPython\u002F.NET).","md",{"badge":699,"tags":700,"date":703,"dateDisplay":704,"image":705},"Web Security",[701,702],"Web","XXE","2025-06-20","Jun 20, 2025","\u002Fthumbnails\u002Fowasp-top-ten-1000.png","\u002Fposts\u002Fxml-external-entity",{"title":5,"description":696},"posts\u002FXML-External-Entity","m64XICEVdKT4ArpR0abinT7taR9K9S4Iqu4tsOSeSqg",1787385494388]