나무모에 미러 (일반/어두운 화면)
최근 수정 시각 : 2024-09-15 14:55:29

버퍼 오버플로

버퍼 오버런에서 넘어옴

파일:나무위키+유도.png  
은(는) 여기로 연결됩니다.
프로그래밍 관련 질의 응답 사이트에 대한 내용은 Stack Overflow 문서
번 문단을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
참고하십시오.
1. 개요2. 왜 문제가 되는가3. 대처법4. 관련 문서

1. 개요

Buffer Overflow

버그의 일종 또는 이를 이용한 공격 방법.

프로그램이 실행될 때 입력받는 값이 버퍼를 가득 채우다 못해 넘쳐흘러 버퍼 이후의 공간을 침범하는 현상. 쉽게 말해 양동이(버퍼)에 물(값)을 받을 때(입력 받기) 물을 너무 많이 받아 바닥에 흘러넘쳐 버리는 것이라고 생각하면 된다.

주로 프로그램이 사용자에게 데이터(주로 문자열)을 입력받을 때 사용자가 말을 곧이곧대로 듣지 않고 이미 준비된 버퍼보다 더 많은 양의 데이터를 입력할 때 발생하지만 해커가 역으로 이용해 임의로 프로그램메모리의 값을(주로 스택) 변조할 때에도 쓰인다.[1]

이 문제는 스택에서 주로 발생하기 때문에 '스택 오버플로(Stack Overflow)'라고도 부른다.

2. 왜 문제가 되는가

버퍼 오버플로가 발생할 시[2] 버퍼에 다 담지 못한 값들은 버퍼 이후의 공간에 들어차게 된다. 문제는 들어차는 방식이 밀어내기가 아닌 덮어쓰기라는 것이다.

가령 8칸짜리 메모리가 있고, 그 안에 4칸짜리 버퍼가 있을 때

파일:attachment/buffer_overflow.png

이와 같이 사용자가 버퍼를 초과하는 값을 입력하면 버퍼 이후의 값이 바뀌게 된다.

문제는 이걸 프로그램은 전혀 모르고 있는 상태라는 것이다.[3] 심지어 버퍼 이후의 값이 바뀌어도 프로그램은 이를 전혀 사용자에게 통지하지 않는다!

중요하지 않은 10줄~50줄짜리 소규모 예제 프로그램이라면 이는 딱히 신경쓰지 않아도 되지만 중형이나 대규모 프로젝트라면 이야기가 달라지는데 이 원리를 통해 해킹이 가능하기 때문이다.

간단한 예를 들자면 10자리 비밀번호를 치고 들어가는 시스템이 있다고 하자. 그리고 비밀번호를 저장하는 값 바로 뒤에 로그인 여부를 묻는 값이 있다고 하자.(0=실패, 이외의 값=성공) 이 상황에서 끝자리가 0이 아닌 11자리 비밀번호를 입력하면 틀리더라도 뚫을 수 있게 된다!

만약 버퍼를 초과하여 쓰여지는 값이 프로그램의 RETN[4]값을 덮어쓰게 된다면 사용자가 프로그램의 진행 상황을 통제할 수 있게 된다. 만약 특정한 함수가 있고, 이 함수의 주솟값을 알고 어떤 입력이 버퍼 오버플로 공격이 가능하다면 그냥 '입력받는 문자열 + 4[5]/8[6]바이트(SFP 덮어쓰기용) + 해당 함수 주소'를 입력값에 쑤셔넣어 입력 함수가 끝나면 자신이 원하는 함수로 점프할 수 있게 된다.

가장 유명한 사례로는 하트블리드 사태와 스타크래프트 1의 EUD가 있다.

3. 대처법

요즘은 컴파일러 레벨에서 이 오버플로에 대한 처리를 다 해 준다. Visual Studio 같은 경우에는 컴파일러가 버퍼 생성 시 앞뒤로 2바이트짜리 영역을 만들어 디버깅시 이 위치의 값이 바뀌면 버퍼 오버플로가 발생한 것으로 판단하고 예외를 때려 버리며 아예 버퍼 오버플로가 발생하기 쉬운 함수(strcpy 등)는 이를 방어 가능한 함수(strcpy_s 등)으로 교체하라고 경고[7]를 해 준다. 물론 이렇게 다 해 준다고 마냥 안심하긴 어려운데 버퍼 오버플로는 프로그램이 Input을 받는 모든 곳에서 발생할 수 있으므로 프로그래머도 값을 입력받을 때 갖가지 예외 처리를 통해[8] 이 값이 과연 올바른 값인지 꼼꼼히 따져봐야 한다.

4. 관련 문서



[1] 이를 임의 코드 실행이라고 하며 고전 게임 등지에서 버그를 통해 메모리 값을 변조시키는 행위를 할 때도 이 용어를 사용한다. 심하면 단순 변조 수준이 아니라 제한된 환경에서 코딩하는 수준까지도 가버린다.[2] 버퍼 오버플로 공격은 C와 같은 프로그래밍 언어에서 strcpy(문자열복사) 등 문자열에 관련된 함수가 경계조건을 검사하지 않기 때문에 발생한다.[3] 물론 이는 로우 레벨까지 프로그래머세세하게 코딩해야 했던 때의 이야기고 요즘은 디버깅시 컴파일러가 버퍼 앞뒤에 오버플로 방어용 1~4바이트짜리 값을 넣어(카나리라고 한다. 어원은 카나리아(조류) 문서 참조) 침범되었을 경우 예외를 때려버리거나 코딩 단계에서 '이 함수는 버퍼 오버플로의 위험이 있음' 이라고 경고를 해 준다. 물론 이 현상이 사라진 건 아니므로 프로그래머는 여전히 버퍼에 들어가는 값을 체크 해야 된다.[4] 현재 함수의 실행이 끝나면 호출 스택을 타고 상위 함수로 올라가는데 이때 쓰이는 값[5] 32비트 프로그램일 경우[6] 64비트 프로그램일 경우[7] VS 2013부터 경고(warning)에서 에러(error)로 변경되어서 컴파일이 안 된다. 설정을 통해 다시 경고 수준으로 바꾸거나, _CRT_SECURE_NO_WARNINGS 구문을 소소코드의 맨 위에 넣어주면 된다.[8] 가령 main 함수의 argv 문자열 값으로 넘어오는 값이 버퍼를 초과할 수 있으므로 int형 변수를 먼저 선언하고 다른 변수를 선언해 argv-int-다른 변수 순으로 쌓이는 스택의 특성을 이용하여 int형 변수의 값이 바뀌면 이를 버퍼 오버플로라 판단해 차단해버리는 스택 가드 기법이 있다.