1) XXE Injection이란 무엇인가?
XML External Entity
XML 외부 개체 주입 → XXE Injection
XML : 데이터를 효율적으로 주고 받기 위해 만들어진 마크업 언어
클라이언트와 서버가 통신할때 어떤 데이터 형식으로 주고 받을지 결정하게되는데, 그 형식이 XML 이다.
최근에는 XML → JSON 으로 데이터 형식이 많이 변경되었다. (JSON 등장 이후 XML 활용빈도 줄어듬)
Entity : 개체 (특정 문자열을 사용할 수 있도록 하는 상용구 역할, 참조) (DTD에 대한 이해가 필요)
XXE Injection이란
XML을 통해 데이터를 주고 받는 기능에 대해서 외부 개체를 주입하는 공격 (외부 개체 참조 - 외부 파일들을 호출)
이를 통해 서버 내 자원(설정파일, 소스코드 등)을 무단 열람할 수 있게된다.
이외에도 SSRF(Server Side Request Forgery), DoS 공격도 가능하다.
2) 공격 대상
Injection 공격은 기능에 따라 발생되는 취약점이 다르다.
SQL Injection
- 웹 어플리케이션과 DB가 연결된 기능에 대해서 사용자 입력값에 SQL 구문을 삽입하여 공격을 한다.
- DB와 연결을 통해 값을 얻어와서 사용자에게 값을 반환하는 기능을 이용한다.
OS Command Injection
- 사용자 입력값을 통해서 시스템 명령을 실행할 수 있는 기능에, 시스템 명령어를 삽입하여 공격을 한다.
- 관리자 콘솔에서 사용하는 시스템 명령어 실행 기능을 이용한다. (백업, 특정 IP에 ping 요청 등)
- 일반적인 웹 사이트에서는 OS Command Injection 취약점을 발견하기 어렵다.
XXE Injection
- XML Parser 기능이 있는 어플리케이션에 대해서 공격을 시도, SYSTEM 사용하여 외부 개체 참조
- 어플리케이션 이용 시 메시지 바디에 XML 형태로 데이터 전송하는지 확인(XML 파싱 기능 확인)
- 최근에는 JSON 형태를 많이 사용하여 거의 없다.(기존 레거시 시스템에는 존재)
3) 공격 원리 분석
정상적인 XML Parser
- 어플리케이션이 XML 파서 기능을 수행, XML 형식의 데이터를 정상적으로 받아서 어플리케이션으로 반환한다.
- 사용자가 어플리케이션 메시지 바디에 직접 XML을 전송 할 수도 있다.
- 사용자가 어플리케이션에 문서 형태로 업로드 할 수도 있다.
- 외부 참조 없이 XML 파서 기능만 수행한다.
비 정상적인 XML Parser
- 어플리케이션이 XML 파서 기능을 수행, XML 내 외부 참조하는 문장을 삽입, 외부 참조 후 어플리케이션으로 반환
- XML 자체에서 외부 개체 참조 (DTD)
- 외부 개체(External Entity) 참조가 불가능한 상황에서는 XXE Injection 공격이 불가능하다.
DTD(Document Type Definition) : 문서 타입 정의 (XML 문서에서 사용할 수 있는 구조, 요소, 속성을 정의)
Entity : 특정 문자열을 사용할 수 있도록 해주는 상용구 역할을 한다. (내부, 외부 엔티티가 존재)
Entity(엔티티) 특수 문자 또는 자주 사용되는 정보들을 선언해 놓고 XML 문서나 DTD에서 참조하여 사용하는 것을 의미. 엔티티를 참조하게 되면 파싱을 할 때 그 엔티티 참조는 선언해 놓은 값으로써 대체되어 지며, XML에서 엔티티는 문서의 단위이고 한 글자에서부터 문서 전체에 이르기까지혹은 또 다른 문서에 대한 참조까지를 의미한다. Entity 참조란? 파서에게 포함시키기를 원하는 문서의 위치를 알려주고 파서가 가져오는 것. 참고: https://ly91.tistory.com/12 |
< 내부 개체 & 외부 개체 >
내부 엔티티
- 문자열이 XML 문서 내부에 존재
- 내부에서 문자열 참조
외부 엔티티
- SYSTEM 사용(외부 파일 호출할 수 있도록 외부 개체 사용)
정상적인 입력 값
- XML 형식으로 요청
비 정상적인 입력 값
- 외부 엔티티를 참조할 수 있도록 DTD 선언
- SYSTEM 사용, 대상 서버가 Linux/Unix 시스템의 경우 etc/passwd 를 자주 참조한다.
실습4-1 XXE Injection 공격 실습
XXE Injection 공격 실습을 위해 127.0.0.1/insecure_website 접속 후 admin 계정으로 로그인한다.
우측 상단의 XML Parser 를 클릭한다.
아래 XML 코드를 XML Input에 입력 후 파싱해본다.
<?xml version="1.0" encoding="UTF-8"?> <test> <person> <name>administrator</name> </person> </test> |
아래와 같은 결과가 출력되는 것을 확인할 수 있다.
name administrator 가 출력된다.
< 내부 개체 참조 >
내부 개체를 먼저 파싱해본다.
administrator 문장이 출력되면 내부 개체가 참조되는 것으로 볼 수 있다.
아래 코드를 입력 후 파싱한다.
<!DOCTYPE a[ <!ENTITY str "administrator"> ]> <print>&str;</print> |
아래와 같이 str administrator 가 출력되었다.
< 외부 개체 참조 >
외부 개체를 참조하기 위해서는 서버 내 특정 파일이 있어야한다.
기존 SQL Injection 실습 시 활용했던 secret_info.txt 파일을 활용한다. (경로: C:\information\secret_info.txt)
아래 코드를 입력 후 파싱한다.
<!DOCTYPE a[ <!ENTITY str SYSTEM "file:///information/secret_info.txt"> ]> <print>&str;</print> |
아래와 같이 파일 내용이 출력되는 것을 확인할 수 있다.
대상 서버가 Windows 시스템의 경우에는 Linux/Unix 시스템보다 공격에 좀 더 제약이 있다.
대상 서버가 Linux/Unix 시스템의 경우에는 공격을 더 활발하게 할 수 있다.
외부에 파일을 호출 할 수 있다면, Linux/Unix 시스템은 참조할 수 있는 파일이 다양하다. (대부분 파일 형태로 존재)
→ 프로세스도 파일로 존재, 각 계정의 홈 디렉터리 확인 가능, 히스토리 파일 확인하여 작업내역 확인 가능, 작업 내역을 통해 설정 파일 위치 등을 파악할 수 있게된다.
만약 내부 파일에 < (꺾쇠)가 있는 경우에는 어떻게 될까?
XML에서 < (꺾쇠)는 메타문자로 XML 요소의 시작을 의미한다.
secret_info.txt 파일 내 내용을 <This is secret_information 로 변경해본다.
다시 XML 파서에 아래 코드를 입력 후 파싱해본다.
<!DOCTYPE a[ <!ENTITY str SYSTEM "file:///information/secret_info.txt"> ]> <print>&str;</print> |
아래와 같이 여러 에러가 발생하게 되며 파싱이 불가능해진다.
< (꺾쇠)가 포함된 소스코드를 참조하게 되면 위와 같이 에러가 발생하게 된다.
서버 사이드 스크립트에서는 < (꺾쇠)를 사용하는데, 그럼 소스코드를 참조할 수 없을까?
JSP : <%
PHP : <?
ASP : <%
→ 인코딩하면 가능
PHP는 BASE64로 인코딩하면 가능하다.
BASE64 인코딩 코드가 추가된 아래 코드를 입력 후 파싱한다.
php://filter/read=convert.base64-encode/resource=
<!DOCTYPE a[ <!ENTITY str SYSTEM "php://filter/read=convert.base64-encode/resource=file:///information/secret_info.txt"> ]> <print>&str;</print> |
아래와 같이 BASE64로 인코딩된 문자열이 출력되는 것을 확인할 수 있다.
BASE64로 인코딩된 문자열은 CyberChef 를 활용하거나, 버프스위트의 디코더 기능을 활용하면 디코딩이 가능하다.
좌측의 From Base64 더블 클릭 후 Input에 인코딩 문자열을 입력하면 Output에 디코딩된 문자열이 출력된다.
버프스위트의 Decoder 클릭 후 Decode as를 Base64로 설정 후 문자열을 입력하면 순수 문자열을 확인할 수 있다.
< 외부 개체 참조 - 소스코드 >
외부에서 참조하는 Base64로 인코딩된 소스코드를 디코딩해본다.
XML Parser 페이지의 소스코드 위치를 파악 후 파싱해본다. (경로: C:\APM_Setup\htdocs\insecure_website\xmlparser.php)
아래 코드를 입력 후 파싱한다.
<!DOCTYPE a[ <!ENTITY str SYSTEM "php://filter/read=convert.base64-encode/resource=file:///APM_setup/htdocs/insecure_website/xmlparser.php"> ]> <print>&str;</print> |
아래와 같이 BASE64로 인코딩된 문자열이 출력되는 것을 확인할 수 있다.
CyberChef 에서 디코딩하니 아래와 같이 소스코드가 출력된다.
버프스위트에서도 디코딩하니 아래와 같이 소스코드가 출력된다.
XXE Injection을 사용하여 웹 서버 내 자원을 무단으로 열람할 수 있는 실습을 진행해보았다.
4) 대응 방안
1. JSON 데이터 형식으로 기능 구현 (변경할 수 있으면 하되, 무조건은 아님)
2. DTD 및 외부 엔티티 비활성화
3. XML Parser 기능 제거
< 외부 개체 참조 비활성화 >
JAVA에서 factory.setFeature 를 사용한다.
→ true 로 설정하여 외부 엔티티에 외부 자원을 포함한 경우 예외가 발생하도록 구현한다.
PHP에서 libxml_disable_entity_loader 를 사용한다.
→ 외부 엔티티를 로그하는 능력을 disable 할 것인지에 대한 설정. false는 외부 엔티티를 가져올 수 있으며, XXE Injection 이 가능하므로 true 로 설정해야한다.
각 어플리케이션에 따라 적용되는 방식이 다르므로 Server Side Script 에 맞는 비활성화 방식을 고려해야한다.
실습4-2 취약 환경 시큐어 코딩 적용 실습
XML Parser 기능이 필요없다면 제거하는게 제일 좋은 방법이다.
하지만 XML Parser 기능을 부득이하게 사용해야 하는 경우, 외부 개체를 참조하는 기능을 비활성화하면 된다.
XXE Injection이 발생되었던 XML Parser 페이지에 대해 시큐어 코딩을 진행한다.
소스코드 위치: C:\APM_Setup\htdocs\insecure_website
< xmlparser.php 의 Action 페이지 >
<?
include_once("./common.php");
$xml = $_POST["xml"];
if(!empty($xml)){
$result = simplexml_load_string($xml);
}
?>
/* HTML 코드 생략 */
<? if(!empty($result)) { ?>
<hr>
<?
print_r($result);
?>
<? } ?>
XML을 사용자로부터 받아온 후 XML 값이 있는 경우, XML을 출력하는 소스코드이다.
< xmlparser.php 의 Action 페이지 - 시큐어 코딩 적용 >
<?
include_once("./common.php");
$xml = $_POST["xml"];
libxml_disable_entity_loader(true);
if(!empty($xml)){
$result = simplexml_load_string($xml);
}
?>
/* HTML 코드 생략 */
<? if(!empty($result)) { ?>
<hr>
<?
print_r($result);
?>
<? } ?>
libxml_disable_entity_loader(true); 추가 후 XML Parser 페이지에서 XXE Injection 을 시도한다.
아래 XML 코드를 입력 후 파싱한다.
<!DOCTYPE a[ <!ENTITY str SYSTEM "php://filter/read=convert.base64-encode/resource=file:///information/secret_info.txt"> ]> <print>&str;</print> |
아래와 같이 failed to load external entity 를 확인할 수 있다.
외부 엔티티 참조가 불가능한 것이다.
DTD 선언 및 내부 개체 참조는 가능하다.
아래 XML 코드를 입력 후 파싱한다.
<!DOCTYPE a[ <!ENTITY str "XXE Injection Secure Coding Complete"> ]> <print>&str;</print> |
아래와 같이 입력한 문자열이 출력되는 것을 확인할 수 있다.
취약한 어플리케이션이 있다면 취약 여부를 테스트 후, 각 어플리케이션에 맞는 시큐어 코딩 구문을 작성한다.
각 어플리케이션마다 적용하는 방법이 다르며, 특히 SQL Injcetion, XSS, 파일 업로드/다운로드 공격은 어플리케이션이 달라도 공통적인 방법이 있으니 각각의 공격방법 및 대응방안을 숙지하도록 한다.
XXE Injection 3줄 요약
- XML 이라는 데이터 형식을 사용하는 어플리케이션 기능에 외부 개체를 주입하는 공격
- SYSTEM 키워드 사용하여 외부 개체 참조하여 서버 내 파일 열람
- 대응방안: JSON으로 데이터 형식 기능 구현, DTD 및 외부 엔티티 비활성화, XML Parser 기능 제거
참고
'웹 해킹 > 웹 해킹 및 시큐어 코딩 기초' 카테고리의 다른 글
XSS (Cross-Site Scripting) (0) | 2025.01.24 |
---|---|
OS Command Injection (2) | 2025.01.03 |
SQL Injection 대응 방안 (1) | 2024.12.27 |
SQL Injection (1) | 2024.12.11 |
버프 스위트(Burp Suite) 설치 및 사용법 (0) | 2024.11.26 |