CVE-2017-12623
Apache NIFI에서 XXE 취약점이 발생하여 조치되었다. 취약 코드와 조치 후 코드를 비교해보자.
취약 코드
final Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller();
unmarshaller.setSchema(schema);
- final JAXBElement<Authorizers> element = unmarshaller.unmarshal(new StreamSource(authorizersConfigurationFile), Authorizers.class);
external entity 제한 없이 XML 파일을 불러와 사용하여 external entity에 삽입된 악의적인 명령을 수행하는 취약점이 발생하였다.
테스트 파일
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><!DOCTYPE object [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
+<object>
+ <name>&xxe;</name>
+ <description>Arbitrary XML that has an XXE attack present.</description>
+ <groupId>3a204982-015e-1000-eaa2-19d352ec8394</groupId>
+ <timestamp>09/05/2017 14:51:01 PDT</timestamp>
+</object>
취약점 이행 점검을 위해 생성한 테스트 파일로 /etc/passwd 파일을 불러오는 내용이 포함되어 있다.
조치 코드
+public class XmlUtils {
+
+ public static XMLStreamReader createSafeReader(InputStream inputStream) throws XMLStreamException {
+ if (inputStream == null) {
+ throw new IllegalArgumentException("The provided input stream cannot be null");
+ }
+ return createSafeReader(new StreamSource(inputStream));
+ }
+
+ public static XMLStreamReader createSafeReader(StreamSource source) throws XMLStreamException {
+ if (source == null) {
+ throw new IllegalArgumentException("The provided source cannot be null");
+ }
+
+ XMLInputFactory xif = XMLInputFactory.newFactory();
+ xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
+ xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
+ return xif.createXMLStreamReader(source);
+ }
+}
external entity를 제한한 XML 파서 클래스를 별도로 생성하였다.
+ final XMLStreamReader xsr = XmlUtils.createSafeReader(new StreamSource(authorizersConfigurationFile));
final Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller();
unmarshaller.setSchema(schema);
+ final JAXBElement<Authorizers> element = unmarshaller.unmarshal(xsr, Authorizers.class);
이전 취약 코드와는 다르게 external entity를 제한한 XML 파서 클래스로 객체를 생성하여 XML을 처리하고 있다.