XML 내부 엔티티 확장으로 인한 서비스 거부 (DoS)
XML Entity Expansion (Billion Laughs)
설명
신뢰할 수 없는 XML을 엔티티 확장이 가능한 상태로 파싱할 때, 공격자가 DTD 내부에 매우 깊이 중첩된 내부 엔티티를 정의하여 작은 입력으로도 기하급수적으로 큰 문자열을 생성하게 만드는 취약점입니다. 이로 인해 파서는 메모리와 CPU를 과도하게 소모하며 서비스 거부(DoS)가 발생합니다. 특히 node-expat처럼 내부 엔티티를 기본 확장하는 파서를 그대로 사용할 경우, 공격자가 빌리언 래프스 형태의 XML을 업로드하거나 전송하는 것만으로 애플리케이션을 멈추게 만들 수 있습니다.
잠재적 영향
서비스 거부(DoS): 과도한 엔티티 확장으로 프로세스가 응답 불가 상태가 됩니다.
메모리 고갈: 확장된 텍스트가 메모리를 점유하여 OOM(메모리 부족)로 프로세스가 종료될 수 있습니다.
CPU 자원 고갈: 엔티티 치환/파싱 반복으로 CPU 사용률이 급상승합니다.
시스템 안정성 저하: 애플리케이션 충돌, 자동 재시작 루프, 장애 전파로 가용성이 떨어집니다.
비용 증가: 오토스케일링 환경에서 불필요한 리소스 확장과 비용이 발생할 수 있습니다.
해결 방법
엔티티 확장 비활성화: 가능한 경우 XML 파서 옵션에서 DTD/Entity 확장을 끄고, DOCTYPE 선언을 거부합니다.
안전한 파서 사용: node-expat처럼 내부 엔티티를 기본 확장하는 라이브러리 대신 sax 같은 스트리밍 파서(사용자 정의 엔티티를 확장하지 않음) 또는 엔티티 확장 제어가 가능한 파서를 사용합니다.
입력 제한: 요청 본문 크기(limit), 파싱 시간(timeout), 노드/깊이/텍스트 길이 제한을 적용합니다.
유효성 검증: 스키마(whitelist) 검증을 적용하고, 입력 내 <!DOCTYPE 등 DTD 관련 토큰이 발견되면 요청을 거부합니다.
방어적 구성: 리버스 프록시/웹서버에서 요청 크기 제한, 애플리케이션에서 작업 큐와 동시성 제한으로 폭주를 억제합니다.
취약한 코드 및 안전한 코드 예시
취약한 코드
안전한 코드
설명:
취약한 코드: node-expat는 내부 엔티티를 기본적으로 확장합니다. 검증 없이 req.body를 그대로 전달하면, 공격자가 중첩된 엔티티(빌리언 래프스)를 포함한 XML을 보내 작은 입력으로도 메모리/CPU를 고갈시켜 DoS를 유발합니다.
안전한 코드: - DOCTYPE/ENTITY가 포함된 XML을 사전에 차단해 DTD 기반 엔티티 확장을 원천 봉쇄합니다.
sax 같은 스트리밍 파서는 사용자 정의 엔티티를 확장하지 않아 내부 엔티티 확장 공격에 강합니다.
요청 본문 크기 제한으로 대용량 입력을 차단하고, 오류 처리를 통해 파싱 중단이 가능합니다.
참조
Last updated