XmlUtil의 XML 외부 엔티티(XXE) 취약점 수정 - #138
Open
EricSeokgon wants to merge 1 commit into
Open
Conversation
DocumentBuilderFactory에 외부 엔티티 차단 설정을 추가해 CWE-611(XXE)을 방지한다. 정적 팩토리 2개와 지역 인스턴스 3개에 applyXxeProtection 헬퍼를 적용했으며, 저장소 자체 방어 패턴(ComResourceUtils:213)과 동형이다. 검증 파서는 DTD 로딩을 유지하도록 외부 엔티티만 차단한다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
수정 사유 Reason for modification
수정된 소스 내용 Modified source
XmlUtil이 XML을 파싱할 때DocumentBuilderFactory에 외부 엔티티 차단 설정을 하지 않아 XXE(XML External Entity Injection, CWE-611) 에 노출됩니다. 미방어 지점은 정적 팩토리 2개(45·46행)와 지역 인스턴스 3개(186·204·227행, 수정 전 기준)입니다.XmlUtil은 이 저장소의 6개 플러그인에서 호출되며, 그중HandlePomXMLFileUtil은 프로젝트의pom.xml을 파싱합니다. 따라서 외부 엔티티가 포함된 XML(예: 악의적pom.xml)이 든 프로젝트를 IDE로 열면 개발자 PC의 로컬 파일이 읽히거나 외부 URL 요청이 발생할 수 있습니다.수정 내용
이 저장소는 이미 같은 방어 패턴을 갖고 있습니다 —
egovframework.dev.imp.commngt의ComResourceUtils.java213행이setFeature계열로 외부 엔티티를 차단합니다. 이 PR은 그 패턴을XmlUtil에 맞춰 넣는 것으로 새 규칙을 도입하지 않습니다.applyXxeProtection(DocumentBuilderFactory, boolean)private 헬퍼를 추가하고 5개 파싱 지점에 적용했습니다(+33/−0). 외부 일반/파라미터 엔티티를 차단해 검증 여부와 무관하게 XXE 파일 읽기를 막습니다. 스키마 검증용vfactory(validating=true)는 DTD 로딩이 필요하므로 외부 엔티티 차단만 적용하고, 비검증 파서에는 외부 DTD 로딩 차단과FEATURE_SECURE_PROCESSING까지 적용했습니다. 파서가 특정 기능을 미지원하면ParserConfigurationException을 무시하고 나머지 방어를 적용합니다.JUnit 테스트 JUnit tests
빌드: 번들된
lib/xalan.jar를 클래스패스로javac단독 컴파일 성공(JDK 21, 오류 0).재현·검증 (수정 전/후 동일 하네스, JDK 21.0.10 —
applyXxeProtection의 실제 로직을 복제해 실행). 공격 XML(<!DOCTYPE r [ <!ENTITY xxe SYSTEM "file://…"> ]>)로 로컬 파일 읽기를 시도:v=[TOP-SECRET-EGOV-2026]v=[]v=[TOP-SECRET-EGOV-2026]v=[]정상 XML 회귀 확인(파싱은 계속 동작해야 함):
v=[정상데이터](정상)v=[정상데이터](정상)수정 후 외부 엔티티는 빈 값으로 무력화되고, 정상 XML 파싱과 스키마 검증 경로는 그대로 동작합니다.
테스트 브라우저 Test Browser
테스트 스크린샷 또는 캡처 영상 Test screenshots or captured video
UI 변경이 없어 스크린샷은 해당하지 않습니다. 위 표의 실측값을 근거로 제시합니다.
참고 — 같은 저장소의 동일 유형 (이 PR 범위 밖): 근본 원인이 같은 XXE 미방어 지점이
dev/mdev ComResourceUtils(각 2곳, 같은 파일의 다른 지점은 이미 방어됨),NexusPropertyPage,QueryIdSearchJob에도 있습니다. 이 PR은 호출자가 가장 많은XmlUtil한 파일로 범위를 한정했으며, 나머지도 동일 방식으로 후속 정리할 수 있습니다. 필요하시면 이 PR에 합치겠습니다.