[Dreamhack] Memory Corruption: Use After Free

#코딩노예#·2022년 7월 18일
0

Dreamhack - System Hacking

목록 보기
30/49

Use After Free

Dangling Pointer : 유효하지 않은 메모리 영역을 가리키는 포인터

malloc() → 할당된 메모리 주소 반환


메모리 동적 할당

1. 포인터를 선언

2. 포인터에 malloc() 함수가 할당한 메모리 주소 저장

3. 포인터를 참조하여 할당한 메모리에 접근


메모리 해제

1. free() 함수 호출

2.  free() 함수가 청크를 ptmalloc에 반환, 청크의 주소를 담고 있던 포인터 초기화 X

free() 함수 호출 이후 프로그래머가 포인터를 초기화하지 않으면, 포인터는 해제된 청크를 가리키는 Dangling Pointer가 됩니다.

Dangling Pointer는 경우에 따라 공격 수단으로 활용될 수 있습니다.




Use-After-Free (UAF)

해제된 메모리에 접근할 수 있을 때 발생하는 취약점

Dangling Pointer로 인해 발생하기도 하지만, 새롭게 할당한 영역을 초기화하지 않고 사용하면 발생

malloc()free() 함수는 할당 또는 해제할 때 메모리 데이터들을 초기화하지 않아서 새롭게 할당된 청크를 프로그래머가 초기화하지 않으면, 메모리에 남아있던 데이터가 유출되거나 사용될 수 있습니다.




취약한 코드(UAF)

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

struct NameTag {
        char team_name[16];
        char name[32];
        void (*func)();
};

struct Secret {
        char secret_name[16];
        char secret_info[32];
        long code;
};

int main() {
        int idx;

        struct NameTag *nametag;
        struct Secret *secret;

        secret = malloc(sizeof(struct Secret));

        strcpy(secret->secret_name, "ADMIN PASSWORD");
        strcpy(secret->secret_info, "P@ssw0rd!@#");
        secret->code = 0x1337;

        free(secret);
        secret = NULL;

        nametag = malloc(sizeof(struct NameTag));

        strcpy(nametag->team_name, "security team");
        memcpy(nametag->name, "S", 1);

        printf("Team Name: %s\n", nametag->team_name);
        printf("Name: %s\n", nametag->name);

        if (nametag->func) {
                printf("Nametag function: %p\n", nametag->func);
                nametag->func();
        }
}

$ ./uaf
Team Name: security team
Name: S@ssw0rd!@#
Nametag function: 0x1337
Segmentation fault

Name으로 secret_info의 문자열이 출력됐고 값을 입력한 적 없는 함수 포인터가 0x1337을 가리키고 있습니다.




UAF 동적 분석

ptmalloc2

→ 새로운 할당 요청이 들어오면 요청된 크기와 비슷한 청크가 bin이나 tcache에 있는지 확인

→ 만약 있다면 해당 청크를 꺼내 재사용

Nametag와 Secret은 같은 크기의 구조체

 → secret를 해제하고 nametag를 할당하면, nametagsecret과 같은 메모리 영역을 사용

 → free는 해제한 메모리의 데이터를 초기화하지 않기 때문에, nametag에는 secret의 값이 일부 남아있게 됨


gef➤  heap-analysis-helper
[*] This feature is under development, expect bugs and unstability...
[+] Tracking malloc() & calloc()
[+] Tracking free()
[+] Tracking realloc()
[+] Disabling hardware watchpoints (this may increase the latency)
[+] Dynamic breakpoints correctly setup, GEF will break execution if a possible vulnerabity is found.
[*] Note: The heap analysis slows down the execution noticeably.
gef➤  c
Continuing.
[+] Heap-Analysis - __libc_malloc(56)=0x602260
[+] Heap-Analysis - free(0x602260)
[+] Heap-Analysis - __libc_malloc(56)=0x602260
[+] Heap-Analysis - __libc_malloc(1024)=0x6022a0
Team Name: security team
Name: S@ssw0rd!@#
Nametag function: 0x1337

Program received signal SIGSEGV, Segmentation fault.

gef➤  x/10gx 0x602260
0x602260:       0x7974697275636573      0x0000006d61657420
0x602270:       0x6472307773734053      0x0000000000234021
0x602280:       0x0000000000000000      0x0000000000000000
0x602290:       0x0000000000001337      0x0000000000000411
0x6022a0:       0x20676174656d614e      0x6e6f6974636e7566
gef➤  x/s 0x602260
0x602260:       "security team"
gef➤  x/s 0x602270
0x602270:       "S@ssw0rd!@#"
gef➤  x/gx 0x602290
0x602290:       0x0000000000001337

초기화되지 않은 secret_info 값과 code  값이 그대로 남아있습니다.

동적 할당한 청크를 해제한 뒤에는 해제된 메모리 영역에 이전 객체의 데이터가 남습니다. 이러한 특징을 이용하면 초기화되지 않은 메모리의 값을 읽거나, 새로운 객체가 악의적인 값을 사용하게 유도하여 프로그램의 정상적인 실행을 방해할 수 있습니다.



Memory Corruption: Use After Free

0개의 댓글