XML 외부 개체(XXE) 엔티티 확장 허용
XML External Entity (XXE)
설명
libxmljs/libxmljs2에서 XML을 파싱할 때 옵션 noent: true를 사용하면 엔티티가 실제 값으로 확장됩니다. 이때 외부 개체(External Entity)까지 해석되어 네트워크나 로컬 파일에 접근할 수 있어 위험합니다. 공격자는 사용자가 업로드한 XML에 DOCTYPE과 외부 엔티티를 선언해 /etc/passwd 같은 로컬 파일을 읽게 하거나, 내부망/메타데이터 엔드포인트로 요청을 보내는 SSRF, 혹은 무한 엔티티 확장(일명 Billion Laughs)으로 DoS를 유발할 수 있습니다.
잠재적 영향
로컬 파일 노출: 외부 엔티티를 통해 애플리케이션이 파일 시스템(예: /etc/passwd)을 읽어 그 내용을 응답이나 로그로 유출할 수 있습니다.
SSRF(서버 측 요청 위조): 파서가 외부 엔티티를 해석하며 내부망/메타데이터 서비스(예: http://169.254.169.254)에 요청을 보내 민감 정보를 획득할 수 있습니다.
서비스 거부(DoS): 거대한/재귀적 엔티티 확장(Billion Laughs)으로 CPU·메모리를 고갈시키고 서비스 중단을 일으킬 수 있습니다.
해결 방법
noent 비활성화: 신뢰할 수 없는 입력을 파싱할 때 noent 옵션을 사용하지 않거나 noent: false로 설정하십시오.
DTD 차단/거부: 입력에 가 포함되면 처리하지 말고 요청을 거절하세요.
필요 시 대체 유틸 사용: &, < 같은 내부 엔티티 처리가 필요하면 lodash.unescape, underscore#unescape, he 등의 라이브러리를 별도로 사용하세요.
입력 검증: 예상 스키마/형식만 허용(allowlist)하고 크기 제한, 타임아웃, 메모리 제한 등 파서 자원 제한을 설정하세요.
원격 접근 제한: 애플리케이션이 임의 URL/파일 프로토콜로 접근하지 못하도록 네트워크 egress 정책과 파일 접근 권한(원칙적 최소 권한)을 강화하세요.
취약한 코드 및 안전한 코드 예시
취약한 코드
안전한 코드
설명:
취약한 코드: noent: true를 사용하면 파서가 엔티티를 실제 값으로 대체합니다. 공격자가 DOCTYPE과 외부 엔티티를 정의한 XML을 보내면 파서가 로컬 파일을 읽거나 임의의 URL에 접속(SSRF)하고, 거대한 엔티티 확장으로 메모리/CPU를 소모해 DoS를 유발할 수 있습니다.
안전한 코드: - DTD 차단으로 외부 엔티티 선언 자체를 막습니다.
noent: false로 외부 엔티티 확장을 비활성화하여 파일/네트워크 접근을 차단합니다.
필요한 경우에만 he 등의 유틸로 텍스트의 내부 엔티티를 안전하게 디코딩하여 기능 요구사항을 충족합니다.
참조
Last updated