Information Security

버퍼 오버플로우 취약점 확인 + 메모리 변조 실습 본문

System Hacking

버퍼 오버플로우 취약점 확인 + 메모리 변조 실습

leeeeye321 2018. 1. 31. 04:56

스택 버퍼 오버플로우(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)는 입력이 되지 않는다.