Information Security
버퍼 오버플로우 취약점 확인 + 메모리 변조 실습 본문
스택 버퍼 오버플로우(stack buffer overflow)
-스택에 정해진 버퍼보다 큰 공격 코드를 삽입하여 반환 주소를 변경함으로써 임의의 공격 코드를 루트 권한으로 실행하도록 하는 방법이다.
-취약한 함수 scanf, gets, strcpy, ... 등을 사용해서 발생하는 취약점이다.
1. 취약점 확인 - strcpy 함수
오버플로우 공격을 시도하기 위해서 취약한 코드를 작성 했다.
strcpy(dest, src);
strcpy 함수로 인해 입력받은 인자가 buffer2로 복사된다.
인자를 전달하면서 파일을 실행하면 buffer2의 값이 출력된다.
이번에는 길이가 긴 인자를 전달했다.
-> 그랬더니 buffer1의 값이 출력되었다. ???
strcpy( buffer2, argv[1] );
이 부분에서 버퍼 오버플로우 취약점이 발생한 결과이다.
★ strcpy 함수는 문자열을 복사할 때 문자열의 길이를 체크하지 않는다.
-> 이 코드에서 버퍼는 20 바이트인데 20 바이트가 넘는 긴 값을 인자로 전달하면 넘쳐 흘러서 다른 메모리를 침범하게 된다.
-> 버퍼2까지 침범하여 넘쳐 흐른 값(Buffer overflow)이 버퍼2에 출력된 것이다.
훨씬 더 긴 인자를 전달했더니 에러(Segmentation fault)가 발생했다.
-> 비정상적인 값을 입력해서 의도적으로 에러를 발생시킬 수 있다.
-> 취약점으로 연결되는 에러이다.
strncpy 함수는 문자열의 길이를 체크하기 때문에 이를 사용하여 취약점을 없앨 수 있다.
20 바이트를 넘는 인자를 전달해도 다른 메모리를 침범하지 않는다.
2. 취약점 확인 - 표준 입력 함수 gets
이번에는 gets 함수로 문자열을 입력받았다.
표준 입력 값도 버퍼의 크기를 넘어가면 다른 메모리를 침범한다.
gdb(디버거)를 통해서 target2의 실행 과정을 볼 수 있다.
비정상적인 값의 입력으로 에러를 발생시켰다.
-> 입력한 인자 중 4바이트가 eip 레지스터에 들어간 것을 확인할 수 있다.
-> eip 레지스터의 값을 변경해서 실행의 흐름을 바꿀 수 있다는 것이다.
메모리 침범 영역 확인
-> 취약점 발생 위치에 따라서 메모리를 변조할 수 있는 위치도 달라진다.
3. 메모리 변조
그러면 이제 메모리를 원하는 값으로 변조해볼 것이다.
이 코드는 인자를 입력하지 않으면 HELLO를 두 번 출력한다.
코드를 변경하지 않고 아래와 같이 출력하려면 어떻게 해야 할까?
HELLO
BYE
인자는 buffer로 복사되는데, 20 바이트를 넘어가면 HELLO 메모리를 침범하게 된다.
-> 침범한 부분부터 BYE로 덮어쓰면 된다.
12345678
87654321
이번에는 이렇게 출력하고 싶다.
-> 그런데 인자는 숫자 형태로 입력할 수 없다. (숫자도 문자로 인식한다.)
-> 문자열 이스케이프를 사용해야 문자열 내에서 숫자 표현이 가능해진다.
위와 같이 파이썬 명령어 치환 $()을 통해서 숫자 표현을 할 수 있다.
★ bad character (인자로 입력할 수 없는 값)
1. 0x00 (NULL)
문자열의 끝을 나타내는 마지막 한 바이트에만 삽입이 가능하다.
-> 입력할 방법이 전혀 없다.
2. 0xff
bash 버그에 의해 입력할 수 없다.
-> bash2로 쉘을 교체하면 입력이 가능해진다.
chsh 명령어로 쉘을 교체할 수 있다.
-> 교체한 쉘은 다음 번 로그인부터 적용된다.
env 명령어로 쉘이 교체된 것을 확인한다.
이제 ff를 입력할 수 있다.
3. 0x20, 0x0a, 0x09
이 값들은 White Space로 인식해서 입력이 되지 않는다.
명령어 치환을 더블 쿼터로 감싸면 숫자로 인식 하여 입력이 가능해진다.
-> Enter(0x0a)는 입력이 되지 않는다.
'System Hacking' 카테고리의 다른 글
스택 버퍼 오버플로우 공격 실습 (0) | 2018.02.01 |
---|---|
권한 상승 기법(Leviathan) (0) | 2018.01.31 |
시스템 콜을 이용한 mkdir 프로그램 작성 (0) | 2018.01.28 |
시스템 콜(System Call) (1) | 2018.01.25 |
main 함수의 인자 argc, argv (0) | 2018.01.24 |