일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Sookmyung Information Security Study
- 웹페이지 만들기
- c
- 숙명여자대학교 정보보안 동아리
- BOJ Python
- XSS Game
- hackerrank
- 풀이
- SWEA
- The Loard of BOF
- 드림핵
- HTML
- 자료구조 복습
- BOJ
- PHP 웹페이지 만들기
- CSS
- 숙명여자대학교 정보보안동아리
- 백준
- 머신러닝
- siss
- lob
- WarGame
- Python
- Javascript
- hackctf
- 생활코딩
- c++
- 기계학습
- C언어
- 파이썬
- Today
- Total
혜랑's STORY
[System Hacking STAGE 8] Memory Corruption: Out of Bounds 본문
[System Hacking STAGE 8] Memory Corruption: Out of Bounds
hyerang0125 2022. 2. 14. 22:48들어가며
- 배열 : 같은 자료형의 요소(Elment)들로 이루어져 있는데, 각 요소의 위치를 인데스(Index)라고 한다.
- 현실에서 첫 번째 요소를 프로그래밍할 때는 0번째 요소라고 한다.
- 위와 같은 실수는 운이 좋으면 프로그램의 비정상 종료로 그치지만, 때에 따라 치명적인 취약점의 원인이 될 수 있따. 그 대표적 예로 배열의 이므이 인덱스에 접근할 수 있는 Out of Bounds(OOB)가 있다.
Out of Bounds
배열의 속성
- 배열은 연속된 메모리 공간을 점유하며, 배열이 점유하는 공간의 크기는 요소의 개수와 요소 자료형의 크기를 곱한 값이 된다. 흔히, 배열이 포함하는 요소의 개수를 배열의 길이(Length)라고도 부른다.
- 배열 각 요소의 주소는 배열의 주소, 요소의 인덱스, 요소 자료형의 크기를 이용하여 계산된다.
Out of Bounds
- OOB는 요소를 참조할 때, 인덱스 값이 음수이거나 배열의 길이를 벗어날 때 발생한다. 개발자가 인덱스의 범위에 대한 검사를 명시적으로 프로그래밍하지 않으면, 프로세스는 앞서 계산한 주소가 배열의 범위 안에 있는지 검사하지 않는다.
- 만약 사용자가 배열 참조에 사용되는 인덱스를 임의 값으로 설정할 수 있따면, 배열의 주소로부터 특정 오프셋에 있는 메모리의 값을 참조할 수 있다. 이를 배열의 범위를 벗어나는 참조라 하여 Out of Bounds 라고 부른다.
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;
}
- 이 예제는 OOB의 이해를 돕기 위한 예제 코드이다. int형 변수 10개를 요소로 하는 배열 arr을 선언하고, 다양한 인덱스를 사용하여 배열 내부와 외부의 주소들을 출력한다.
- 결과에서 주목해야 할 것은 컴파일러(gcc)는 배열의 범위를 명백히 벗어나는 -1과 100을 인덱스로 사용했음에도 아무런 경고를 띄워주지 않는다. 즉, OOB를 방지하는 것은 전적으로 개발자의 몫이다.
- 두 번째로 arr[0]와 arr[100]의 주소 차이가 0x7ffff650f93e0 - 0x7fff650f9250 = 0x190 = 100 * 4이다. 배열의 범위를 벗어난 인덱스를 참조해도 앞서 살펴본 식을 그대로 사용함을 확인할 수 있다.
임의 주소 읽기
- OOB로 임의 주소의 값을 읽으려면, 읽으려는 변수와 배열의 오프셋을 알아야 한다. 배열과 변수가 같은 세그먼트에 할당되어 있다면, 둘 사이의 오프셋은 항상 일정하므로 디버깅을 통해 쉽게 알아낼 수 있다. 만약 같은 세그먼트가 아니라면, 다름 취약점을 통해 두 변수의 주소를 구하고, 차이를 계산해야 한다.
- 인덱스에 대한 검증이 미흡해 임의 주소 읽기가 가능한 예제 코드이다.
// Name: oob_read.c
// Compile: gcc -o oob_read oob_read.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char secret[256];
int read_secret() {
FILE *fp;
if ((fp = fopen("secret.txt", "r")) == NULL) {
fprintf(stderr, "`secret.exe` does not exist");
return -1;
}
fgets(secret, sizeof(secret), fp);
fclose(fp);
return 0;
}
int main() {
char *docs[] = {"COMPANY INFORMATION", "MEMBER LIST", "MEMBER SALARY",
"COMMUNITY"};
char *secret_code = secret;
int idx;
// Read the secret file
if (read_secret() != 0) {
exit(-1);
}
// Exploit OOB to print the secret
puts("What do you want to read?");
for (int i = 0; i < 4; i++) {
printf("%d. %s\n", i + 1, docs[i]);
}
printf("> ");
scanf("%d", &idx);
if (idx > 4) {
printf("Detect out-of-bounds");
exit(-1);
}
puts(docs[idx - 1]);
return 0;
}
- 길이가 3인 배열 docs를 참조하는데, 인덱스 값이 3보다 큰지만 검사하고, 음수인지는 검사하지 않는다. ==> docs와 secret_code은 모두 스택에 할당되어 있으므로, docs에 대한 OOB를 이용하면 secret.txt 파일을 만들고 oob_read의 OOB를 이용하여 secret.txt의 값을 읽을 수 있다.
임의 주소 쓰기
- OOB를 이용하면 임의 주소에 값을 쓰는 것도 가능하다.
- 인덱스에 대한 검증이 미흡해 임의 주소에 값을 쓸 수 있는 예제이다.
// Name: oob_write.c
// Compile: gcc -o oob_write oob_write.c
#include <stdio.h>
#include <stdlib.h>
struct Student {
long attending;
char *name;
long age;
};
struct Student stu[10];
int isAdmin;
int main() {
unsigned int idx;
// Exploit OOB to read the secret
puts("Who is present?");
printf("(1-10)> ");
scanf("%u", &idx);
stu[idx - 1].attending = 1;
if (isAdmin) printf("Access granted.\n");
return 0;
}
- 24바이트 크기의 Student 구조체 10개를 포함하는 배열 stu와 isAdmin를 전역 변수로 선언한다. 그리고 사용자로부터 인덱스를 입력받아서 인덱스에 해당하는 Student 구조체의 attending에 1을 대입한다.
- 코드의 마지막 부분을 보면 isAdmin이 참인지 검사하는 부분이 있다. 해당 변수에 값을 직접 쓰는 부분은 없지만 코드에 OOB취약점이 있으므로 이를 이용하여 isAdmin의 값을 조작할 수 있다.
- 디버거로 stu와 isAdmin의 주소를 확인해보면, isAdmin이 stu보다 240바이트 높은 주소에 있음을 알 수 있다.
- 즉, 배열을 구성하는 Studen 구조체의 크기가 24바이트이므로, 10번째 인덱스를 참조하면 isAdmin을 조작할 수 있다.
- OOB 취약점을 공격하여 isAdmin 값을 조작할 수 있다.
'무지성 공부방 > Dreamhack SystemHacking' 카테고리의 다른 글
[System Hacking STAGE 9] Memory Corruption: Format String Bug (0) | 2022.02.17 |
---|---|
[System Hacking STAGE 8] out_of_bound (0) | 2022.02.15 |
[System Hacking STAGE 7] hook (0) | 2022.02.13 |
[System Hacking STAGE 7] oneshot (0) | 2022.02.13 |
[System Hacking STAGE 7] Exploit Tech: Hook Overwrite (0) | 2022.02.09 |