일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 교수님제발
- Network IP
- 리버싱기초
- BOB9기
- https://youtu.be/quLIdcHgi1k?t=694
- ip class
- 기초
- DB 종류 찾기
- 가변 페이지 사이즈
- 과제
- Network
- page_size
- 100만원이하
- SIBAL
- 암호생성
- SQL 실습
- 웹취약점
- OSI 7Layer
- 보호기법
- 가성비노트북
- c언어
- 90만원대
- Host IP
- 'or1=1
- 드림핵
- 취약점종류
- SQL Injection
- 웹해킹기초
- 칼럼수찾기
- DB 추측 방법
- Today
- Total
us1s
버퍼 오버 플로우_01 본문
버퍼 오버 플로우 (Buffer Over Flow, 이하 'BOF')
= "Buffer가 넘쳐 흐른다."
즉, 입력한 문자열이 선언한 변수(배열)의 크기보다 더 커질때, 다른 용도로 사용하는 영역에 값을 덮어쓰게 된다.
BOF에 취약한 함수로는 "strcpy, strcat, gets, scanf ... 등이 있다.
이러한 함수의 공통적인 특징은 처리하는 문자열의 최대 크기를 정하지 않는다는 점이다.
다음은 메모리의 구조이다.
STACK |
HEAP |
BSS |
DATA |
TEXT(code) |
각 영역에 대한 설명이다.
- Stack : 함수에 대한 정보를 포함
- Heap : 동적 할당된 변수를 할당 ex)malloc etc...
- BSS : 초기화되지 않은 변수 할당
- Data : 초기화된 변수 할당
- Text : 코드를 기계어로 대입
Stack 은 선입후출 (First In Last Out) 구조를 가지고 있다.
먼저 들어간 것은 나중에 나오고, 나중에 들어간것은 먼저 나온다 .
// BOF 예시 코드
#include <stdio.h>
void stack1()
{
int x = 10;
stack2();
}
void stack2()
{
int y = 5;
}
void main()
{
stack1();
return 0;
}
위의 코드가 실행될 때의 Stack Frame의 변화를 알아보자.
- main 함수가 stack 함수의 주소를 알고 있다.
- 하지만 stack 함수는 main 함수의 주소를 모른다.
- 그래서 Stack Frame에 main 함수 복귀 주소를 저장한다. → `main() RET`
- 하지만 stack 함수는 main 함수의 주소를 모른다.
- stack1 함수가 호출되었으므로 1번과 동일하게 stack1 함수의 복귀 주소를 저장한다. → `stack1() RET`
- 이후 정수형 변수 x을 선언한 뒤, 10으로 초기화 하였다. → `x`
- stack2 함수를 호출한다. stack2 의 복귀 주소를 저장한다. → `stack2() RET`
- stack2 함수가 호출 되었고 정수형 변수 y를 선언한 뒤, 5로 초기화하였다. → `y`
이렇게 만들어진 Stack Frame은 다음과 같다.
5) Y 4) Stack2() RET 3) X 2) Stack1() RET 1) main() RET
쌓인 순서는 1→2→3→4→5 순이다.
Stack은 선입후출 구조를 가지므로,
사용 순서는 5→4→3→2→1 순이다.
* RET 다음 순서에는 RBP가 들어가야한다. RBP는 스택이 시작된다는 알리는 용도로 사용된다.
* RBP 와 RET의 크기는 운영체제가 32bit일때 4byte, 64bit일때 8byte의 크기를 가진다.
이제 BOF를 이해하기 위한 밑그림이 끝났다.
이전 Stack Frame 을 살펴보자.
다음과 같다.
3) buffer ( 16 byte ) |
2) RBP ( 8 byte ) |
1) main() RET |
3번에 값을 넣을수 있는 Buffer가 있다.
이전에 말했던 BOF의 문제점이 무엇인가?
입력한 문자열이 선언한 변수(배열)의 크기보다 더 커질때, 다른 용도로 사용하는 영역에 값을 덮어쓰게 된다.
즉, 3번 Buffer에 16byte를 초과하는 값을 입력한다면 2번 RBP값을 덮어씌워진다.
이때, 2,3번을 합한 크기 24byte 를 초과하여 입력한다면 RET에 사용자가 원하는 값을 입력할 수 있게 된다.
정확히는 스택 오버 플로우라고 한다.
여튼 이를 이용하여 해커가 원하는 명령을 실행할 수 있다.
예를 들면, 리눅스에선 SetUID가 있다.
SetUID가 설정된 프로그램이 실행되면, 해당 프로그램이 실행될 때 UID가 SetUID를 설정한 유저A의 것으로 변경된다.
이때 BOF를 일으킨 프로그램의 SetUID가 root로 되어있다면,
해당 프로그램 실행될 동안 해당 유저A는 root권한을 얻게 된다.
예방법
- 값을 받거나 저장하면서 변수의 범위를 검사하지 않는 함수 사용을 자제한다.
- ASLR 기술을 사용한다. ( ASLR = 주소공간 배치를 난수화 한다. )
- Stack Shield 를 이용한다. ( Global RET 라는 특수 스택에 함수 복귀주소를 따로 저장한 뒤 복귀 시 비교하여 진행)
- 무결성 체크 방법 (버퍼와 RET사이 무결성 복귀 값 "Canary"을 대입, 변조될 시 Ret 실행 안함)
'sOFT wARE' 카테고리의 다른 글
네트워크 기초_02 (0) | 2020.06.27 |
---|---|
SQL Injection_01 (0) | 2020.06.26 |
MySQL 5.6_dump (2) | 2020.06.26 |
네트워크 기초_01 (0) | 2020.06.25 |
어셈블리_기초_01 (0) | 2020.06.22 |