1.2 XML 조회 및 결과 검증
개요
XML(Extensible Markup Language)은 데이터 교환 및 저장에 널리 사용되는 형식입니다. XML 데이터를 처리할 때, 외부 입력값을 사용하여 XPath나 XQuery 같은 XML 질의 언어를 동적으로 생성하거나, XML 파서가 외부 리소스를 참조하도록 허용하는 경우 보안 취약점이 발생할 수 있습니다.
대표적인 취약점으로는 XPath/XQuery 삽입(SQL 삽입과 유사하게 질의문을 조작)과 XML 외부 개체 참조(XXE, XML External Entity) 공격이 있습니다. XXE 공격은 공격자가 서버의 로컬 파일을 읽거나, 내부 네트워크의 다른 시스템에 접근(SSRF)하는 등 심각한 피해를 유발할 수 있습니다.
또한, XML 조회 결과를 검증하지 않으면 의도치 않은 데이터가 노출될 수 있습니다. 이 기준은 XML 조회 및 파싱 시 입력값 처리와 결과 검증에 대한 보안 요구사항을 정의합니다.
보안 대책
- - 입력값 검증 및 이스케이프: XPath/XQuery 구문에 사용되는 외부 입력값에서 특수문자를 필터링하거나 이스케이프 처리합니다.
- - 매개변수화된 질의 사용: 가능하다면, SQL의 Prepared Statement와 같이 XPath/XQuery에서도 매개변수화된 방식을 사용하여 입력값이 질의 구조를 변경하지 못하도록 합니다. (라이브러리 지원 여부 확인 필요)
- - 외부 개체(External Entity) 비활성화: XML 파서 설정에서 외부 DTD(Document Type Definition) 및 외부 개체 참조 기능을 명시적으로 비활성화합니다. 이는 XXE 공격을 방어하는 가장 근본적인 방법입니다.
- - 안전한 XML 파서 사용 및 설정: 보안 기능이 강화된 최신 버전의 XML 파서를 사용하고, 보안 관련 설정을 확인하여 적용합니다.
- - 결과 검증: XML 조회 결과가 예상된 구조와 데이터 형식을 따르는지 확인합니다.
코드 예시 (Java - XXE 방지)
XPath/XQuery 삽입 방지는 SQL 삽입과 유사하게 입력값 검증 및 가능하다면 매개변수화된 쿼리 사용이 중요합니다. 아래는 XXE 취약점을 방지하기 위한 Java 코드 예시입니다.
취약한 코드 (기본 설정):
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import java.io.StringReader;
// 기본 설정의 DocumentBuilderFactory는 XXE에 취약할 수 있음
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// 외부 입력을 포함한 XML 문자열 (예시)
String xmlInput = "<?xml version=\"1.0\"?><!DOCTYPE foo [...]><data>...</data>";
Document doc = db.parse(new InputSource(new StringReader(xmlInput))); // XXE 공격 가능성
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import java.io.StringReader;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// XXE 방지를 위한 보안 설정 추가
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // DTD 자체를 금지 (가장 강력)
// 또는 아래 기능들을 비활성화
// dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
// dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
// dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
DocumentBuilder db = dbf.newDocumentBuilder();
String xmlInput = "<?xml version=\"1.0\"?><data>...</data>"; // DTD 없는 안전한 XML
Document doc = db.parse(new InputSource(new StringReader(xmlInput))); // XXE 방어됨
Python(lxml, xml.etree.ElementTree), JavaScript(DOMParser), C#(System.Xml), C(libxml2) 등 다른 언어에서도 각 라이브러리가 제공하는 옵션을 통해 외부 개체 로딩을 비활성화하는 것이 중요합니다.