FlawOpen

flawopen.com/XXE/Java XML 파서 보안

Java XXE: DocumentBuilderFactory는 기본적으로 안전한가요?

CWE-611: Improper Restriction of XML External Entity ReferenceJava XML 참고 가이드
짧은 답: 외부 접근은 기본 차단되지 않습니다

JDK는 일부 안전 처리 제한을 기본 적용하지만 DOM 및 SAX 기본 설정은 외부 리소스 접근을 차단하지 않습니다. 애플리케이션이 명시적으로 제한하지 않으면 XML이 파일이나 네트워크 접근을 유발할 수 있습니다. 타사 JAXP Provider가 기본 파서를 대체하면 동작도 달라질 수 있습니다. Java 버전만으로 안전성을 추정하지 말고 실제 파서를 설정하세요.

취약한 설정
DocumentBuilderFactory factory =
    DocumentBuilderFactory.newInstance();
DocumentBuilder builder =
    factory.newDocumentBuilder();
Document document = builder.parse(untrustedXml);

// Java 9+: JAXP 제한을 명시적으로 활성화합니다.
// 필수 설정을 지원하지 않으면 안전하게 중단합니다.
// 파서는 기본적으로 외부 접근을 허용할 수 있습니다.
강화된 설정
DocumentBuilderFactory factory =
    DocumentBuilderFactory.newDefaultInstance();

// 실제 파일이나 서비스로 테스트하지 마세요.
factory.setFeature(
    XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature(
    "http://apache.org/xml/features/"
    + "disallow-doctype-decl", true);
factory.setAttribute(
    XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setXIncludeAware(false);

// 크기 제한은 별도로 적용합니다.
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(untrustedXml);

DOCTYPE 거부가 권장되는 DOM 제어인 이유

파서가 지원하면 DOCTYPE 거부로 DTD에 정의된 외부 엔티티와 선언 처리를 막을 수 있습니다. FEATURE_SECURE_PROCESSING을 명시적으로 켜고 외부 DTD 접근도 제한하세요. JDK에서 FSP가 기본 활성화되어도 외부 연결이 차단된다는 뜻은 아닙니다. 필요하지 않으면 XInclude를 끄세요. 필수 설정을 Provider가 지원하지 않으면 부분 강화 상태로 계속하지 말고 파서 초기화를 실패 처리하세요.

DTD가 필요해도 외부 접근을 허용하지 마세요. 외부 일반/매개변수 엔티티와 외부 DTD 로딩을 끄고 ACCESS_EXTERNAL_DTD를 빈 문자열로 설정하며 처리 제한을 유지하세요. setExpandEntityReferences(false)는 트리 표현을 바꿀 뿐 외부 리소스 차단을 대신하지 않습니다.

각 JAXP 프로세서를 별도로 강화하세요

같은 정책은 XML 처리 전반에 적용되지만 API별 설정이 다릅니다. SAXParserFactory/XMLReader, StAX XMLInputFactory, TransformerFactory, SchemaFactory, Validator, JAXB를 확인하세요. StAX는 FEATURE_SECURE_PROCESSING을 지원하지 않으므로 자체 속성으로 DTD와 외부 엔티티를 끄세요. 외부 스키마와 스타일시트도 제한하고 OWASP의 API별 예시 및 실제 Provider를 확인하세요.

단일 파서 설정을 JVM 전체 보호로 보면 안 됩니다. JAXP Provider 검색 결과가 JDK 내장 파서와 다를 수 있고 복합 프로세서는 내부 파서를 만들 수 있습니다. 운영에서 쓰는 runtime, Provider, 코드 경로를 테스트하세요.

자주 묻는 질문

FEATURE_SECURE_PROCESSING은 기본적으로 외부 엔티티를 차단하나요?

기본 활성화만으로는 차단되지 않습니다. Oracle 문서에 따르면 기본 FSP는 처리 제한을 적용하지만 API에서 명시적으로 켜거나 외부 접근 속성을 설정하기 전까지 외부 연결은 허용됩니다. 정책을 명시하고 Provider를 확인하세요.

최신 JDK에서 기본값이 바뀌었나요?

JDK는 제한과 처리 한도를 추가했지만 Oracle JAXP 가이드는 기본 FSP와 명시적인 외부 접근 차단을 구분합니다. 타사 Provider도 다를 수 있으므로 버전이나 classpath 기본값에 의존하지 마세요.

정상 문서에 DTD가 필요한 경우는?

가능하면 신뢰할 수 있는 로컬 카탈로그나 resolver를 사용하세요. DTD가 필요하면 외부 프로토콜과 엔티티 로딩을 막고 JAXP 제한을 유지하며 필요하지 않으면 XInclude를 끄세요. DOCTYPE 거부보다 복잡하므로 실제 Provider와 정상 문서로 테스트하세요.

출처 및 참고자료

함께 보기 XML 외부 엔터티(XXE) 인젝션(CWE-611): 동작 원리와 방어 방법 — flawopen.com Python XML XXE 보안: ElementTree, Expat, lxml .NET XmlReader는 XXE에 안전한가요?