🇰🇷 한글 설명
Apache OpenNLP의 DictionaryEntryPersistor 클래스가 SAX 파서의 보안 기능을 활성화하지 않아, 악성 DOCTYPE 선언을 포함한 사전 파일을 통해 XXE 공격이 가능합니다. 공격자가 조작된 사전 파일을 제공하면 로컬 파일 공개(file://) 또는 SSRF(http://) 공격을 트리거할 수 있습니다.
💡 쉬운 설명
OpenNLP에서 사전 파일을 로드할 때 악의적인 파일이 전달되면, 공격자가 서버의 파일을 읽거나 다른 서버로 요청을 보낼 수 있습니다. 파일 형식 검증이 제대로 되지 않아 발생하는 취약점입니다.
🇺🇸 원문 (English)
XML External Entity (XXE) via Unsanitized Dictionary Parsing in Apache OpenNLP DictionaryEntryPersistor
Versions Affected: before 2.5.9, before 3.0.0-M3
Description: The DictionaryEntryPersistor class initializes a static SAXParserFactory at class-load time without enabling FEATURE_SECURE_PROCESSING or disabling DTD processing. When create(InputStream, EntryInserter) is invoked, the only feature set on the XMLReader is namespace support — external entity resolution and DOCTYPE declarations remain fully enabled. An attacker who can supply a crafted dictionary file (e.g., a stop-word list or domain dictionary) containing a malicious DOCTYPE declaration can trigger local file disclosure via file:// entity references or server-side request forgery via http:// entity references during SAX parsing, before the application processes a single dictionary entry. This is inconsistent with the project's own XmlUtil.createSaxParser() helper, which correctly sets FEATURE_SECURE_PROCESSING and disallow-doctype-decl and is used by all other XML parsing paths in the codebase. The public Dictionary(InputStream) constructor delegates directly to this method and is the documented API for loading user-supplied dictionaries, making untrusted input a realistic scenario.
Mitigation: 2.x users should upgrade to 2.5.9. 3.x users should upgrade to 3.0.0-M3. Users who cannot upgrade immediately should ensure that all dictionary files are sourced from trusted origins and should consider wrapping the Dictionary(InputStream) constructor with input validation that rejects any XML containing a DOCTYPE declaration before it reaches the parser.
📍 영향받는 시스템
Apache OpenNLP 2.5.9 이전, 3.0.0-M3 이전
⚔️ 공격 벡터
악성 DOCTYPE 선언을 포함한 XML 사전 파일을 Dictionary() 생성자에 전달
🛡️ 대응 방법
OpenNLP를 2.5.9 이상 또는 3.0.0-M3 이상으로 업그레이드하거나, 모든 사전 파일을 신뢰할 수 있는 출처에서만 로드
🔧 검증 코드
표시된 버전이 2.5.9 이상(2.x) 또는 3.0.0-M3 이상(3.x)이면 안전, 그 이하면 업그레이드 필요
find ~/.m2/repository -name '*opennlp-tools*.jar' 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | sort -V | tail -1