대부분의 소프트웨어는 완벽하지 않다. 소프트웨어에 존재하는 결함은 버그 (bug)라고 부른다. 보안 문제를 일으키는 버그를 취약점 (vulnerability)이라고 부른다. 공격자가 취약점을 이용하여 수행하는 보안 공격을 익스플로잇 (exploit)이라고 한다. 즉, 취약점은 익스플로잇을 할 수 있는 버그이다.
제로데이 공격 (0-day attack)
소프트웨어의 취약점이 발견되고 패치되기 까지는 어느정도 시간이 필요하다. 아직 패치가 나오지 않은 취약점을 제로데이 취약점 (0-day vulnerability)이라고 부른다. 패치가 나오지 않은 시점에 이루어지는 보안 공격을 제로데이 공격 (0-day attack) 이라고 한다.
버퍼오버플로우 (buffer overflow)
int main() {
int buffer[10];
buffer[12] = 55;
}
다음의 코드를 실행하면 어떤 일이 벌어질까?
임시메모리공간에buffer[10](10개의공간)을할당
buffer[12] 위치의 메모리에 55이 할당된다.
입력 받는 데이터의 크기가 버퍼의 크기를 벗어나는지 제대로 체크하지 않을 경우 공격자는 버퍼를 벗어난 메모리 의 공간의 데이터를 수정할 수 있다.(혹은 자신이 원하는 값 을 쓸 수 있다.)
C언어에서 사용자 입력을 받는 gets() 함수는 버퍼의 크기를 체크할 수 없어 버퍼 오버플로에 취약하다.
Morris worm이 gets() 함수의 취약점을 이용했다.
char buf[100]; // 100바이트짜리 버퍼
gets(buf); // 입력 데이터가 100바이트를 넘기는지 확인하지 않는다.
buffer overflow의 대응책
[첫 번째]
스택 카나리아(stack canary)
카나리아라는 명칭은 탄광의 유독 가스 를 알아차리기 위해 카나리아라는 새를 이용한 데에서 유래
Stack canary라는 임의의 난수 값을 스택 메모리의 리턴 주소 전에 저장해 둔다.
공격자가 스택 메모리 공간을 덮어써서 리턴 주소를 조작할 경우, 중간에 위치한 stack canary가 손상된다는 점을 이용해 함수 리턴 전에 stack canary를 확인하는 방법
컴파일러에서 제공하는 보안 기능이다.
[두 번째]
데이터 실행 방지(DEP, data execution prevention)
OS에서 제공하는 보안 기능으로, 실행 금지(NX)라고도 부름.
메모리 할당 시에 읽기/쓰기/실행 속성을 지정할 수 있는데, 데이터 영역 메모리는 실행 금지(NX)로 함
해커가 임의의 코드를 데이터 영역에 실어서 실행하는 것을 차단
두가지방식이있다.
CPU 차원에서의 하드웨어 지원
소프트웨어 에뮬레이션: 스레드 태스크 스위칭 시 코드 주소를 확인 하여 실행 속성이 없는 메모리일 경우 실행을 중단
[세 번째]
데이터 실행 방지(DEP, data execution prevention) - Windows 10의 Windows 보안 설정
반환 지향형 프로그래밍 (ROP : Return-Oriented Programming)
DEP를 우회하기 위해 고안된 코드 취약점
메모리 상에 존재하는 라이브러리 함수 코드 일부를 가져와서 리턴 주소 체인을 만들어 실행시키는 방식
정상적으로 존재하는 코드 메모리의 일부를 이용했으므로 DEP에 의해 차단되지 않는다.
ROP 의 대응책
ASLR(Address Space Layout Randomization)
해커가ROP에쓰이는코드조각의메모리주소를알수없도 록 메모리 공간의 배치를 랜덤화한다.
OS에서 제공하는 보안 기능이다.
Windows 10의 Windows 보안 설정 ( 밑에 그림 참고)
FSB (Format String Bug)
서식 문자열 버그(FSB, Format String Bug)
C언어에서 콘솔 출력을 수행하는 printf 함수는 서식 문자열과 출력할 데이터를 인자로 전달받는다.
문자열데이터str을출력할때printf(“%s”,str)대신 printf(str) 형태로 출력할 경우 서식 문자열 버그에 취약하다.
Printf 함수에 의해서 해석되는 “str”은 출력하고자 하는 문자열이 아 니라 printf 함수에서 사용할 각종 형식 지시자(%d, %s 등)를 포함한 format string으로 인식한다.
따라서출력하려는문자열내에지시자(directive)가들어있으면, printf 함수에 전달된 인자의 개수와는 상관없이 이러한 형식 지시자 의 개수 만큼의 인자들이 스택으로부터 추출된다.
공격자는 입력되는 str 문자열에 % 기호를 포함시켜 서식 문자열을 구성 할 수 있다. 서식 문자열 중 %n은 공격자는 이것을 이용하여 메모리 값을 조작할 수 있다.
%n형식은format string내에서%n지시자 전에 지정된출력되어야 하는 모든 공간의 개수를 해당 변수로 저장한다.
예) int val; printf(“aaaa%n”, &val); // val에 문자의 개수인 4가 대입된다.
printf 함수가 %n 지시자를 만나면 이 지시자의 순서에 해당하는 내용을 스택에서 pop하고 pop된 내용을 주소로 하여 해당 주소에 지금까지 출력 된 문자의 개수를 저장하게 된다. 이때 만약 이 주소가 어떤 함수의 리턴 주소가 저장되어 있는 곳이라면 프로그램의 흐름이 변경될 수 있다.
FSB (Format String Bug) 의 대응책
시스템 차원에서는 대응할 수 없고 컴파일러 차원에서 대응하고 있다.
FSB를 예방하기 위해 많은 C/C++ 컴파일러에서 printf(str)와 같은 문장을 경고로 처리한다.
또, 많은 C/C++ 컴파일러에서 표준이 아닌 서식 문자 인 %n의 지원을 없애 FSB를 이용한 메모리 조작의 가능 성을 없앴다.
그러나 FSB를 이용하여 민감한 정보를 읽어보는 것은 여 전히 가능하기에 printf(str)와 같은 문장은 피해야 한다.