[포너블] Out of Bounds

Chris Kim·2024년 10월 22일

시스템해킹

목록 보기
18/33

출처 드림핵

1. Out of Bounds

1.1 배열의 속성

배열이 점유하는 공간의 크기는 요소의 개수와 요소 자료형의 크기를 곱한 값이 된다. 요소의 개수를 우리는 배열의 길이라고 부른다. 배열의 각 주소는 배열의 주소, 요소의 인덱스, 요소 자료형의 크기를 이용하여 계산된다.

1.2 Out of Bounds

OOB는 인덱스 값이 음수거나 배열의 길이를 벗어날 때 발생한다. 이는 프로세스가 배열의 주소를 계산할 때, 그 주소가 배열의 범위 내에 있는지 검사하지 않기 때문이다. 따라서 배열의 주소로부터 특정 오프셋에 있는 메모리의 값을 참조할 수 있다. 이를 배열의 범위를 벗어나는 참조라 하여 Out of Bounds라고 한다.

1.3 Proof-of-Concept

// Name: oob.c
// Compile: gcc -o oob oob.c

#include <stdio.h>

int main() {
  int arr[10];

  printf("In Bound: \n");
  printf("arr: %p\n", arr);
  printf("arr[0]: %p\n\n", &arr[0]);

  printf("Out of Bounds: \n");
  printf("arr[-1]: %p\n", &arr[-1]);
  printf("arr[100]: %p\n", &arr[100]);

  return 0;
}

1.4 임의 주소 읽기(쓰기)

OOB를 이용해 임의 주소의 값을 읽으려면, 읽으려는 변수와 배열의 오프셋을 알아야한다. 배열과 변수가 같은 세그먼트에 할당되어 있다면, 둘 사이의 오프셋은 항상 일정하므로 디버깅을 통해 쉽게 알아낼 수 있다. 만약 그렇지 않다면, 다른 취약점을 통해 두 변수의 주소를 구하고, 차이를 계산해야 한다.

2 Exploit Tech

문제 출처

2.1 분석 및 설계

$ checksec out_of_bound
[*]
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

ASLR, NX, Canary가 적용되어 있다.

소스코드는 다음과 같다.

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

char name[16];

char *command[10] = { "cat",
    "ls",
    "id",
    "ps",
    "file ./oob" };
void alarm_handler()
{
    puts("TIME OUT");
    exit(-1);
}

void initialize()
{
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    signal(SIGALRM, alarm_handler);
    alarm(30);
}

int main()
{
    int idx;

    initialize();

    printf("Admin name: ");
    read(0, name, sizeof(name));
    printf("What do you want?: ");

    scanf("%d", &idx);

    system(command[idx]);

    return 0;
}

2.2 익스플로잇

idx 범위를 검사하지 않기 때문에, OOB를 활용할 수 있다. commandname 전역변수는 PIE가 꺼져있기 때문에, 실행시마다 일정한 주소에 위치한다. 따라서 command 배열에 적절한 인덱스를 집어 넣으면 name에 접근할 수 있다.
따라서 name"/bin/sh\x00"을 저장하고 적절한 인덱스로 이를 가리켜 보자. 참고로 system 함수는 eax 레지스터의 값을 받는데, 이때 레지스터에는 "/bin/sh\x00"을 가리키는 주소 가 들어가야 한다.

2.3 페이로드 작성

따라서 페이로드 구성은 | /bin/sh\x00<8byte>| /bin/sh\x00을 가리키는 주소<4byte> | 다.

profile
회계+IT=???

0개의 댓글