* PoC: Function Pointer Protection in C Programs
@ 2013-08-21 15:00 Stephen Röttger
2013-08-21 17:55 ` Ondřej Bílka
2013-08-22 7:11 ` [oss-security] " Hannes Frederic Sowa
0 siblings, 2 replies; 10+ messages in thread
From: Stephen Röttger @ 2013-08-21 15:00 UTC (permalink / raw)
To: oss-security, gcc
Hi everyone,
I'd like to present you my master's thesis "Malicious Code Execution
Prevention through Function Pointer Protection" [0] and its
proof-of-concept implementation [1] for the gcc+glibc and would
appreciate some feedback.
In my thesis, I tried to find a way to prevent the exploitation of
memory corruption vulnerabilities, in which an attacker is able to
control the content of a function pointer variable and also bypass ASLR
(e.g. by brute force or an information leak). The former is given for
example in use-after-free scenarios comparable to CVE-2013-0170 [2].
In the general case, the attacker can either control parameters to the
function pointer as well and execute e.g. system() directly, or he will
have to call a stack pivoting gadget to have the stack pointer point to
attacker-controlled memory.
Approach:
The basic idea of the thesis is to record all addresses that are
assigned to a function pointer variable at some place in the program (or
in one of the shared libraries) and if a function pointer is called,
verify that the address has been recorded previously. Thus, if an
attacker overwrites the fp variable with either the address of system()
or of a stack pivoting gadget, the fp call will fail, since these
adresses have never been assigned to a function pointer in the program.
The security of the approach relies on the assumption that no function
that can be abused for malicious purposes is ever assigned to a function
pointer, but this requirement will be weakened under future work.
How this works:
The compiler, GCC in my PoC, will register all assignments of function
pointer variables in the source code and will create a global variable
for the assigned function, which is initialized to the function's
address. Then, it replaces the address of the function in the assignment
with the address of the newly created variable:
fp f = &printf;
becomes:
printf_var = &printf;
...
fp f = &printf_var;
Further, a global constructor is created that is run before the main
function of the program or before the shared library is loaded. This
constructor allocates a memory area where it stores the address of each
fp address previously registered. The created global variable is then
overwritten to point to the new memory area instead. Finally, the memory
area is mapped read only. Also, the variable where the address of this
area is stored has to be in read only memory as well to prevent
malicious overwrites. Putting it all together, the memory layout looks
like this:
<read only>
+-------+ +------------+ +------------------+ +----------+
| fp f | -> | printf_var | -> | protected memory | -> | printf() |
+-------+ +------------+ +------------------+ +----------+
Additional instructions are emitted by the compiler before function
pointer calls. They will verify that the global variable (printf_var)
points to the protected memory region, from which it extracts the real
function pointer to be called. If an attacker is able to overwrite
either the function pointer or the global variable, he will only be able
to execute functions contained in the protected memory area (which he
can't overwrite since it is mapped read only during normal execution).
Implementation:
The protection and verification code is moved to a shared library,
libgcc at the moment.
In order to work, the glibc and the runtime linker required some manual
modifications, for example manual protection of code addresses, but most
programs should not need any modifications at all. An exception might be
JIT compilers or any code that wants to call an address that does not
belong to a function.
Performance:
Though my PoC implementation is not free of bugs, I was able to compile
an nginx webserver and have it serve static websites, which I used for a
performance evaluation. On my test system, the number of requests per
second that the nginx could was reduced to 96% compared to a nginx
without the scheme. Handling of a single request included 71 function
pointer calls in this case. (More details can be found in my thesis [0])
Security:
Unfortunately, I already found a way to bypass the scheme if the
attacker controls the first parameter passed to the call of the
overwritten function pointer, but I will present future work that will
prevent this bypass.
The problem is that the glibc uses internal dlopen and dlsym functions
as function pointers. As a consequence, an attacker will be able to
abuse these functions to execute arbitrary code. (dlopen by providing a
shared library with a constructor or by using dlsym to acquire an
arbitrary callable function pointer. section 6.2.2 in my thesis)
Future work:
Through the protected memory area, the possibility exists to store
additional meta information next to the function pointer. This can be
used to a) store the type of the function pointer and only allow calls
using compatible types and b) assign groups to function pointers and
prohibid calls if the groups do not match.
The first approach will further narrow down the possibilities of an
attacker. If he can overwrite a single function pointer variable, he
will only be able to call functions with a matching signature.
The second approach, requires an extension to the C language that is not
standard conformant (e.g. using the gcc __attribute__ syntax) as well as
manual annotation in the source code. But it could be used for example,
to assign a group to the internally used dynamic linking routines and
prevent that they're abused by an attacker.
Feedback and criticism is very welcome, also if anything is unclear feel
free to ask.
Regards,
Stephen
[0] http://zero-entropy.de/fpp.pdf
[1] git://zero-entropy.de/fpp_autobuild.git
[2] http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-0170
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: PoC: Function Pointer Protection in C Programs
2013-08-21 15:00 PoC: Function Pointer Protection in C Programs Stephen Röttger
@ 2013-08-21 17:55 ` Ondřej Bílka
2013-08-21 19:42 ` Stephen Röttger
2013-08-22 7:11 ` [oss-security] " Hannes Frederic Sowa
1 sibling, 1 reply; 10+ messages in thread
From: Ondřej Bílka @ 2013-08-21 17:55 UTC (permalink / raw)
To: Stephen Röttger; +Cc: oss-security, gcc
On Wed, Aug 21, 2013 at 04:43:13PM +0200, Stephen Röttger wrote:
> Hi everyone,
>
> I'd like to present you my master's thesis "Malicious Code Execution
> Prevention through Function Pointer Protection" [0] and its
> proof-of-concept implementation [1] for the gcc+glibc and would
> appreciate some feedback.
>
>
> Performance:
> Though my PoC implementation is not free of bugs, I was able to compile
> an nginx webserver and have it serve static websites, which I used for a
> performance evaluation. On my test system, the number of requests per
> second that the nginx could was reduced to 96% compared to a nginx
> without the scheme. Handling of a single request included 71 function
> pointer calls in this case. (More details can be found in my thesis [0])
>
What is performance impact for program that just qsorts big array? It
looks like worst case scenario for me.
Well now when gcc-4.7 can resolve function pointers it is possible to
create header to inline comparison but still.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: PoC: Function Pointer Protection in C Programs
2013-08-21 17:55 ` Ondřej Bílka
@ 2013-08-21 19:42 ` Stephen Röttger
2013-08-22 13:51 ` Ondřej Bílka
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Röttger @ 2013-08-21 19:42 UTC (permalink / raw)
To: Ondřej Bílka; +Cc: oss-security, gcc
> What is performance impact for program that just qsorts big array? It
> looks like worst case scenario for me.
I just put together a quick test program that sorts an array of 10^6
integers and stopped the execution time using "time". The results are as
follows (+- 0,01s):
protection disabled, -O0:
./sort_nofpp_0 0,19s user 0,02s system 98% cpu 0,215 total
protection enabled, -O0
./sort_fpp_0 0,54s user 0,01s system 99% cpu 0,549 total
protection disabled, -O3
./sort_nofpp_3 0,15s user 0,01s system 98% cpu 0,157 total
protection enabled, -O3
./sort_fpp_3 0,51s user 0,00s system 99% cpu 0,511 total
So this makes quite a difference:
0,19s -> 0,54s
0,15s -> 0,51s
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [oss-security] PoC: Function Pointer Protection in C Programs
2013-08-21 15:00 PoC: Function Pointer Protection in C Programs Stephen Röttger
2013-08-21 17:55 ` Ondřej Bílka
@ 2013-08-22 7:11 ` Hannes Frederic Sowa
2013-08-22 14:08 ` Stephen Röttger
1 sibling, 1 reply; 10+ messages in thread
From: Hannes Frederic Sowa @ 2013-08-22 7:11 UTC (permalink / raw)
To: oss-security; +Cc: gcc
Hi!
On Wed, Aug 21, 2013 at 04:43:13PM +0200, Stephen Röttger wrote:
> Approach:
> The basic idea of the thesis is to record all addresses that are
> assigned to a function pointer variable at some place in the program (or
> in one of the shared libraries) and if a function pointer is called,
> verify that the address has been recorded previously. Thus, if an
> attacker overwrites the fp variable with either the address of system()
> or of a stack pivoting gadget, the fp call will fail, since these
> adresses have never been assigned to a function pointer in the program.
> The security of the approach relies on the assumption that no function
> that can be abused for malicious purposes is ever assigned to a function
> pointer, but this requirement will be weakened under future work.
>
> How this works:
> The compiler, GCC in my PoC, will register all assignments of function
> pointer variables in the source code and will create a global variable
> for the assigned function, which is initialized to the function's
> address. Then, it replaces the address of the function in the assignment
> with the address of the newly created variable:
> fp f = &printf;
> becomes:
> printf_var = &printf;
> ...
> fp f = &printf_var;
> Further, a global constructor is created that is run before the main
> function of the program or before the shared library is loaded. This
> constructor allocates a memory area where it stores the address of each
> fp address previously registered. The created global variable is then
> overwritten to point to the new memory area instead. Finally, the memory
> area is mapped read only. Also, the variable where the address of this
> area is stored has to be in read only memory as well to prevent
> malicious overwrites. Putting it all together, the memory layout looks
> like this:
> <read only>
> +-------+ +------------+ +------------------+ +----------+
> | fp f | -> | printf_var | -> | protected memory | -> | printf() |
> +-------+ +------------+ +------------------+ +----------+
> Additional instructions are emitted by the compiler before function
> pointer calls. They will verify that the global variable (printf_var)
> points to the protected memory region, from which it extracts the real
> function pointer to be called. If an attacker is able to overwrite
> either the function pointer or the global variable, he will only be able
> to execute functions contained in the protected memory area (which he
> can't overwrite since it is mapped read only during normal execution).
Thanks for doing research in this area! :)
Your approach seems to have some slight similarities with -fvtable-verify:
<http://gcc.gnu.org/ml/gcc-patches/2012-11/txt00001.txt>
Maybe some code sharing could be achieved?
Greetings,
Hannes
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: PoC: Function Pointer Protection in C Programs
2013-08-21 19:42 ` Stephen Röttger
@ 2013-08-22 13:51 ` Ondřej Bílka
2013-08-22 14:22 ` Stephen Röttger
0 siblings, 1 reply; 10+ messages in thread
From: Ondřej Bílka @ 2013-08-22 13:51 UTC (permalink / raw)
To: Stephen Röttger; +Cc: oss-security, gcc
On Wed, Aug 21, 2013 at 07:04:58PM +0200, Stephen Röttger wrote:
>
> > What is performance impact for program that just qsorts big array? It
> > looks like worst case scenario for me.
>
> I just put together a quick test program that sorts an array of 10^6
> integers and stopped the execution time using "time". The results are as
> follows (+- 0,01s):
>
> protection disabled, -O0:
> ./sort_nofpp_0 0,19s user 0,02s system 98% cpu 0,215 total
>
> protection enabled, -O0
> ./sort_fpp_0 0,54s user 0,01s system 99% cpu 0,549 total
>
> protection disabled, -O3
> ./sort_nofpp_3 0,15s user 0,01s system 98% cpu 0,157 total
>
> protection enabled, -O3
> ./sort_fpp_3 0,51s user 0,00s system 99% cpu 0,511 total
>
> So this makes quite a difference:
> 0,19s -> 0,54s
> 0,15s -> 0,51s
After bit of thought a loops with callback can be optimized by gcc.
It could be possible to teach CSE to rewrite
while(foo){
check(p);
(*p)(x,y,z);
}
into
check(p);
while(foo){
(*p)(x,y,z);
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [oss-security] PoC: Function Pointer Protection in C Programs
2013-08-22 7:11 ` [oss-security] " Hannes Frederic Sowa
@ 2013-08-22 14:08 ` Stephen Röttger
0 siblings, 0 replies; 10+ messages in thread
From: Stephen Röttger @ 2013-08-22 14:08 UTC (permalink / raw)
To: oss-security; +Cc: Hannes Frederic Sowa, gcc
> Your approach seems to have some slight similarities with -fvtable-verify:
> <http://gcc.gnu.org/ml/gcc-patches/2012-11/txt00001.txt>
>
> Maybe some code sharing could be achieved?
Thanks for the hint, this project was actually a big inspiration for my
thesis and is part of my related work, although I made some mistakes in
its description.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: PoC: Function Pointer Protection in C Programs
2013-08-22 13:51 ` Ondřej Bílka
@ 2013-08-22 14:22 ` Stephen Röttger
0 siblings, 0 replies; 10+ messages in thread
From: Stephen Röttger @ 2013-08-22 14:22 UTC (permalink / raw)
To: Ondřej Bílka; +Cc: oss-security, gcc
> After bit of thought a loops with callback can be optimized by gcc.
>
> It could be possible to teach CSE to rewrite
>
> while(foo){
> check(p);
> (*p)(x,y,z);
> }
>
> into
>
> check(p);
> while(foo){
> (*p)(x,y,z);
> }
>
This might introduce security issues, if an attacker is able to
overwrite p during the execution of the loop.
For example if p is part of a dynamically allocated struct that has
already been freed and an attacker can reallocate the memory after the
first execution of the loop body, he would be able to bypass the check.
On the other hand, if p is stored on the stack, vulnerabilities allowing
to overwrite it, would likely also allow to overwrite saved return
addresses.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: PoC: Function Pointer Protection in C Programs
2013-08-21 16:53 ` Stephen Röttger
@ 2013-08-21 17:05 ` Alessandro Cresto Miseroglio
0 siblings, 0 replies; 10+ messages in thread
From: Alessandro Cresto Miseroglio @ 2013-08-21 17:05 UTC (permalink / raw)
To: Stephen Röttger; +Cc: oss-security, gcc
I'm terrible sorry, I've just seen the first couple of pages and I was
wrong...thanks.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: PoC: Function Pointer Protection in C Programs
2013-08-21 16:26 Alessandro Cresto Miseroglio
@ 2013-08-21 16:53 ` Stephen Röttger
2013-08-21 17:05 ` Alessandro Cresto Miseroglio
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Röttger @ 2013-08-21 16:53 UTC (permalink / raw)
To: Alessandro Cresto Miseroglio; +Cc: oss-security, gcc
The pdf is in english, just parts of the cover and the affirmation are
in german.
On 21.08.2013 17:28, Alessandro Cresto Miseroglio wrote:
> in English?
> (http://zero-entropy.de/fpp.pdf is in Deutsch)
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: PoC: Function Pointer Protection in C Programs
@ 2013-08-21 16:26 Alessandro Cresto Miseroglio
2013-08-21 16:53 ` Stephen Röttger
0 siblings, 1 reply; 10+ messages in thread
From: Alessandro Cresto Miseroglio @ 2013-08-21 16:26 UTC (permalink / raw)
To: Stephen Röttger; +Cc: oss-security, gcc
in English?
(http://zero-entropy.de/fpp.pdf is in Deutsch)
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2013-08-22 10:07 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-21 15:00 PoC: Function Pointer Protection in C Programs Stephen Röttger
2013-08-21 17:55 ` Ondřej Bílka
2013-08-21 19:42 ` Stephen Röttger
2013-08-22 13:51 ` Ondřej Bílka
2013-08-22 14:22 ` Stephen Röttger
2013-08-22 7:11 ` [oss-security] " Hannes Frederic Sowa
2013-08-22 14:08 ` Stephen Röttger
2013-08-21 16:26 Alessandro Cresto Miseroglio
2013-08-21 16:53 ` Stephen Röttger
2013-08-21 17:05 ` Alessandro Cresto Miseroglio
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).