안녕하세요! 👋 웹 보안의 숨겨진 위험을 찾아 떠나는 여러분, 오늘은 2017년 OWASP Top 10에서 네 번째 자리를 차지했던 A4: XML 외부 개체(XML External Entity, XXE)에 대해 알아보겠습니다.

XML은 웹 초창기부터 데이터를 교환하는 데 널리 쓰여온 유서 깊은 형식입니다. 하지만 이 오래된 기술의 편리한 기능 하나가 어떻게 시스템을 위협하는 무서운 칼날이 될 수 있는지, 그 원리와 방어법을 상세히 파헤쳐 보겠습니다. 🧐
🤔 XML과 XXE, 도대체 무슨 관계일까요?
먼저 XML에 대해 간단히 알아볼까요? XML(eXtensible Markup Language)은 HTML처럼 데이터를 태그로 감싸서 구조적으로 표현하는 언어입니다. 유연성이 높아 과거 웹 서비스나 설정 파일 등에서 아주 많이 사용되었죠.
XML의 강력한 기능 중 하나는 문서 구조를 정의하고 재사용 가능한 요소를 미리 선언할 수 있는 DTD(Document Type Definition)입니다. 그리고 이 DTD 안에서 '개체(Entity)'라는 것을 정의할 수 있는데, 이것이 바로 문제의 시작점입니다.
개체(Entity)는 일종의 '바로 가기' 또는 '변수'와 같습니다. 예를 들어, &myname;을 'Paul'이라는 문자열로 미리 정의해두면, 문서 전체에서 &myname;을 쓸 때마다 'Paul'로 자동 변환됩니다.
여기서 더 나아가 '외부 개체(External Entity)'는 문서 외부의 파일이나 URL의 내용을 가져와 개체로 정의하는 기능입니다. 원래는 분리된 데이터를 편리하게 참조하기 위해 만들어졌지만, 공격자들은 이 기능을 악용합니다.
XXE(XML External Entity) 공격은 바로 이 지점에서 발생합니다. 공격자는 악의적으로 조작된 외부 개체가 포함된 XML 데이터를 애플리케이션에 전송합니다. 만약 XML 파서(XML을 해석하는 처리기)가 이 외부 개체를 아무런 검증 없이 처리하면, 공격자는 서버 내부의 파일을 읽거나, 다른 시스템을 공격하는 등 심각한 피해를 줄 수 있습니다. 💣
공격 시나리오: XXE는 어떻게 시스템을 파괴하는가
XXE 공격은 다양한 형태로 나타날 수 있습니다. 대표적인 시나리오 몇 가지를 살펴보겠습니다.
1. 서버 내부 파일 유출 (가장 흔한 유형)
공격자는 외부 개체의 경로를 로컬 파일로 지정하여 서버의 민감한 파일 내용을 빼돌릴 수 있습니다.
공격용 XML 페이로드 예시:
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>&xxe;</foo>
- <!DOCTYPE foo [...]>: DTD를 정의하는 부분입니다.
- <!ENTITY xxe SYSTEM "file:///etc/passwd">: xxe라는 외부 개체를 선언하고, 그 내용을 시스템의 /etc/passwd 파일(사용자 계정 정보가 담긴 민감한 파일)로 지정합니다.
- <foo>&xxe;</foo>: xxe 개체를 호출합니다.
만약 XML 파서가 이 XML을 처리하면, &xxe; 부분은 /etc/passwd 파일의 내용으로 치환됩니다. 그리고 애플리케이션이 이 결과를 공격자에게 다시 보여준다면, 서버의 사용자 계정 정보가 그대로 유출되는 것이죠. 😱
2. 서버 측 요청 위조 (SSRF, Server-Side Request Forgery)
외부 개체는 로컬 파일뿐만 아니라 특정 URL을 참조할 수도 있습니다. 공격자는 이를 악용하여 공격 대상 서버가 내부망의 다른 서버나 외부 시스템에 대신 요청을 보내도록 조종할 수 있습니다.
공격용 XML 페이로드 예시:
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin">
]>
<foo>&xxe;</foo>
위 예시는 클라우드(AWS) 환경에서 내부 메타데이터에 접근하여 관리자(admin)의 임시 보안 자격 증명을 탈취하려는 시도입니다. 일반적인 방법으로는 접근할 수 없는 내부 시스템의 정보를 XXE 취약점을 통해 빼내는 것이죠.
3. 서비스 거부 공격 (DoS, Denial of Service)
'Billion Laughs Attack'이라고도 불리는 이 공격은 재귀적으로 정의된 개체를 사용하여 XML 파서에 과부하를 일으킵니다.
공격용 XML 페이로드 예시:
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
... (계속해서 10배씩 늘어남)
]>
<lolz>&lol9;</lolz>
&lol9;가 최종적으로 처리될 때 수십억 개의 'lol' 문자열이 생성되어 메모리를 고갈시키고 시스템을 마비시킵니다. 😂 -> 😵
🛡️ XXE 공격, 이렇게 막을 수 있습니다!
다행히 XXE는 대부분의 최신 XML 파서에서 간단한 설정 변경으로 효과적으로 방어할 수 있습니다.
1. 외부 개체 및 DTD 기능 비활성화 (가장 확실한 방법)
XML의 외부 개체 기능을 사용하지 않는다면, 파서 레벨에서 이 기능을 완전히 비활성화하는 것이 가장 안전하고 확실한 해결책입니다.
언어별 설정 예시:
- Java:
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); factory.setFeature("http://xml.org/sax/features/external-general-entities", false); factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); - PHP:
libxml_disable_entity_loader(true); - Python:
from lxml import etree # 기본적으로 lxml은 외부 개체를 비활성화하지만, 명시적으로 설정 가능 parser = etree.XMLParser(resolve_entities=False) etree.fromstring(xml_data, parser)
2. 화이트리스트 기반의 입력값 검증
XML 데이터를 받아야 한다면, 데이터의 유효성을 서버 측에서 항상 검증해야 합니다. 정해진 스키마(XSD)를 따르는지 확인하고, 허용되지 않은 요소나 개체 선언이 포함되어 있는지 검사하는 것이 좋습니다.
3. 최신 XML 파서 사용 및 패치 유지
오래된 XML 라이브러리나 파서는 보안에 취약할 수 있습니다. 항상 최신 버전을 유지하고 보안 패치를 정기적으로 적용해야 합니다.
XXE는 2021년 OWASP Top 10에서는 A5: 보안 설정 오류(Security Misconfiguration)의 일부로 통합되었습니다. 이는 개발자가 프레임워크나 라이브러리의 기본 설정을 그대로 사용할 때 XXE와 같은 취약점이 발생하기 쉽다는 것을 의미합니다.
데이터를 처리할 때는 항상 "사용자의 입력은 믿을 수 없다"는 원칙을 명심하고, 사용하는 기술의 보안 설정을 꼼꼼히 확인하는 습관을 갖는 것이 중요합니다.
'일반IT > IT보안' 카테고리의 다른 글
| 🔩 빠진 나사 하나가 모든 것을 무너뜨린다: OWASP A6:2017 - 잘못된 보안 구성(Security Misconfiguration) (3) | 2025.08.16 |
|---|---|
| 🚪"출입금지" 팻말이 무색할 때: OWASP A5:2017 - 취약한 접근 통제(Broken Access Control) (5) | 2025.08.16 |
| 🤫쉿! 당신의 정보가 새고 있어요: OWASP A3:2017 - 민감한 데이터 노출 (4) | 2025.08.16 |
| 🔐 "내 계정이 내 계정이 아니야!" OWASP A2:2017 - 취약한 인증(Broken Authentication) 완전 정복 (2) | 2025.08.16 |
| 😱 웹 애플리케이션의 오랜 숙적: OWASP A1:2017 - 인젝션(Injection) 파헤치기 (1) | 2025.08.16 |