Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Buffer overflow prevention

2 views
Skip to first unread message

Eygene A. Ryabinkin

unread,
Aug 13, 2003, 2:03:34 PM8/13/03
to
Hi!
I have an idea on buffer overflow prevention. I doubt that it's new, but I
haven't seen an implementation of it in any freely distributable Un*x system.
So, I hardly need your comments on it.

Preliminary: I'm talking about Intel x86 architecture, but maybe it will be
applicable to others as well.

The idea itself: all (correct me if I'm wrong) buffer overflows are based on
the fact that we're using the stack, referenced by SS:ESP pair, both for
procedure return address and for local variables. It seems to me, that would we
have two stacks -- one for real stack and one for variables -- it will solve
a bunch of problems. So, my suggestion: let us organise two segments: one for
normal stack, growing downwards, referenced by SS:ESP pair and the second one,
for local variables, referenced by GS:EBP pair, with either upwards or
downwards growing. Now, if we use first segment for passing variables and
procedure return addresses (normal stack usage), and second segment only for
local procedure variables, we will have the following advantages:
1) Local variables and return address will be physically (by means of CPU)
divided and it will not be possible to touch the return address by
overflowing local buffer.
2) The procedure introduces only one extra register -- GS, since EBP is
very often used for the stack frame.
Of course, this two segments can be made non-executable, just in case.

What we need to implement the idea: first, rewrite kernel to organise two
segments for every process and to place proper values into the segment
registers upon the program startup. Second, rewrite the compiler to support
the new scheme of local variables addresation. So, the changes are minimal,
in some sence.

As I said, I hardly need your criticism, suggestions, etc. of any type.
rea

Nicholas Weaver

unread,
Aug 13, 2003, 2:19:58 PM8/13/03
to
On Wed, Aug 13, 2003 at 02:28:33PM +0400, Eygene A. Ryabinkin composed:

> I have an idea on buffer overflow prevention. I doubt that it's
> new, but I haven't seen an implementation of it in any freely
> distributable Un*x system. So, I hardly need your comments on it.

Then why post this to a public list? Sorry, you are going to get
comments.

> Preliminary: I'm talking about Intel x86 architecture, but maybe it will be
> applicable to others as well.

> The idea itself: all (correct me if I'm wrong) buffer overflows are
> based on the fact that we're using the stack, referenced by SS:ESP
> pair, both for procedure return address and for local variables. It
> seems to me, that would we have two stacks -- one for real stack and
> one for variables -- it will solve a bunch of problems. So, my
> suggestion: let us organise two segments: one for normal stack,
> growing downwards, referenced by SS:ESP pair and the second one, for
> local variables, referenced by GS:EBP pair, with either upwards or
> downwards growing. Now, if we use first segment for passing
> variables and procedure return addresses (normal stack usage), and
> second segment only for local procedure variables, we will have the
> following advantages:

> 1) Local variables and return address will be physically (by means
> of CPU) divided and it will not be possible to touch the return
> address by overflowing local buffer.

> 2) The procedure introduces only one extra register -- GS, since EBP is
> very often used for the stack frame.

On the x86, introducing ONE extra reserved register into the calling
convention is a performance killer: the ISA is far too register poor
already.

> Of course, this two segments can be made non-executable, just in case.

> What we need to implement the idea: first, rewrite kernel to organise two
> segments for every process and to place proper values into the segment
> registers upon the program startup. Second, rewrite the compiler to support
> the new scheme of local variables addresation. So, the changes are minimal,
> in some sence.
>
> As I said, I hardly need your criticism, suggestions, etc. of any type.

This only stops attacks which overwrite the return address pointers on
the stack, it doesn't stop heap overflows or other control-flow
attacks.

As such, it seems like this only stops the same class of attacks which
StackGuard-style checking halts: manipulation of the return address
pointer through data overflows.

Since stackguard-techniques already exist, are very mature, and is
included as "On By Default" on OpenBSD and potentially on other
platforms (including possibly Windows, it is in Microsoft's latest
compiler and I think that all new code from Microsoft turns on this
compiler flag [1]), there is no sense inventing new structures, which
require substantially more changes to the infrastructure, which don't
offer any more protection.

[1] If microsoft doesn't have this flag turn on on their own products,
this would be a lawsuit waiting to happen.

--
Nicholas C. Weaver nwe...@cs.berkeley.edu

Crispin Cowan

unread,
Aug 13, 2003, 2:25:03 PM8/13/03
to
Eygene A. Ryabinkin wrote:

> I have an idea on buffer overflow prevention. I doubt that it's new, but I
>haven't seen an implementation of it in any freely distributable Un*x system.
>So, I hardly need your comments on it.

>...


> The idea itself: all (correct me if I'm wrong) buffer overflows are based on
>the fact that we're using the stack, referenced by SS:ESP pair, both for
>procedure return address and for local variables. It seems to me, that would we
>have two stacks -- one for real stack and one for variables -- it will solve
>a bunch of problems. So, my suggestion: let us organise two segments: one for
>normal stack, growing downwards, referenced by SS:ESP pair and the second one,
>for local variables, referenced by GS:EBP pair, with either upwards or
>downwards growing. Now, if we use first segment for passing variables and
>procedure return addresses (normal stack usage), and second segment only for
>local procedure variables, we will have the following advantages:
>

This is approximately what StackShield
<http://www.angelfire.com/sk/stackshield/info.html> does. However, it
does not appear to have been maintained since 2000.

Crispin

--
Crispin Cowan, Ph.D. http://immunix.com/~crispin/
Chief Scientist, Immunix http://immunix.com
http://www.immunix.com/shop/


Michal Zalewski

unread,
Aug 13, 2003, 3:59:33 PM8/13/03
to
On Wed, 13 Aug 2003, Eygene A. Ryabinkin wrote:

[ BUGTRAQ is probably not the best place for such a discussion, but
I'm not sure SECPROG is still alive and kicking, so... ]

> I have an idea on buffer overflow prevention.

Well, no, strictly speaking, you don't =) You have an idea for preventing
one of the symptoms, which is eip overwrite. Overwriting other stack
variables, pointers and flags in particular, or causing overflows
elsewhere in the memory would still be as lethal. But I'm too picky... to
the point.

The concept itself isn't particularly new, but I think that prior takes on
it considered splitting the call/ret and parameter stacks, instead of
local variables vs everything else. The latter is indeed a neat idea,
because it does not require major changes to the entire system at once -
the calling convention remains the same.

For a lesser performance impact, you should just keep arrays and alloca()
buffers in the secondary stack, I think. Since you need to modify the
compiler anyway, I think it's a wiser decision than putting everything on
the secondary stack. Besides, by keeping single integers (often used for
flags or to keep other vital parameters) and pointers away from the
buffers, you make it in some cases more difficult to take over the
application.

It has an advantage over non-executable stack patch, address randomization
or stack canaries in that it prevents ret address manipulation altogether,
making it impossible to return into PLT, program code, libc or whatnot, so
it's a nice idea.

--
------------------------- bash$ :(){ :|:&};: --
Michal Zalewski * [http://lcamtuf.coredump.cx]
Did you know that clones never use mirrors?
--------------------------- 2003-08-13 21:14 --


Michal Zalewski

unread,
Aug 13, 2003, 6:22:14 PM8/13/03
to
On Wed, 13 Aug 2003 wei...@metux.de wrote:

> Some languages offer runtime range checking, which should bring much
> security, but often is really slow :(

In the times of Java and XML used for almost everything, it's not like we
strive for every single CPU cycle nowadays in common applications and are
willing to sacrifice everything else for that. There are exceptions,
particularly in the multimedia domain, but codecs and drivers aren't a
common attack vector anyway, so we don't need range checking there that
badly. For other code, extra CMPL or so is really not that expensive.

The reason why most programmers don't use neat languages with strong
typing, range control, exception handling, pointers kept away from the
programmer, etc - unless they have to, of course - is quite different...
in fascist and easily readable languages, you feel being controlled, not
in control. We prefer to be in control to being instructed by an overly
picky machine, even if we evidently can't handle the situation in a
competent manner.

Plus, the point when code compiles and "just works" is further away,
because you need to resolve issues you wouldn't be aware of in C.

--
------------------------- bash$ :(){ :|:&};: --
Michal Zalewski * [http://lcamtuf.coredump.cx]
Did you know that clones never use mirrors?

--------------------------- 2003-08-13 23:06 --

wei...@metux.de

unread,
Aug 13, 2003, 7:15:24 PM8/13/03
to
On Wed, Aug 13, 2003 at 12:13:27PM -0700, Nicholas Weaver wrote:

<snip>


> This only stops attacks which overwrite the return address pointers on
> the stack, it doesn't stop heap overflows or other control-flow
> attacks.

ACK. Often there are function pointers stored on the heap - so this
does not really help much.

It would be better to invest more time in fail-checking code, i.e.
in C: macros for memory operations which do range checks:

>>>>
static inline _sec_strcpy(char* dest, const char* src, int max)
{
int i;
if ((!dest)||(max<1)) return -1;
if ((max==0)||(!src)) return -1;
{
dest[0] = 0;
return 0;
}
i = strncpy(dest,src,max);
dest[max] = 0;
return i;
}

#define STRCPY_BUF(buffer,src) _sec_strcpy(&buffer, src, sizeof(buffer));
<<<<

Some languages offer runtime range checking, which should bring much security,
but often is really slow :(

<snip>


> [1] If microsoft doesn't have this flag turn on on their own products,
> this would be a lawsuit waiting to happen.

why (in detail) should they be attackable ? did they give any warranty ?

cu
--
---------------------------------------------------------------------
Enrico Weigelt == metux ITS
Webhosting ab 5 EUR/Monat. UUCP, rawIP und vieles mehr.

phone: +49 36207 519931 www: http://www.metux.de/
fax: +49 36207 519932 email: con...@metux.de
cellphone: +49 174 7066481
---------------------------------------------------------------------
Diese Mail wurde mit UUCP versandt. http://www.metux.de/uucp/

Craig Pratt

unread,
Aug 13, 2003, 7:18:39 PM8/13/03
to

On Wednesday, Aug 13, 2003, at 03:28 US/Pacific, Eygene A. Ryabinkin
wrote:
> Hi!

> I have an idea on buffer overflow prevention. I doubt that it's new,
> but I
> haven't seen an implementation of it in any freely distributable Un*x
> system.
> So, I hardly need your comments on it.
>
> Preliminary: I'm talking about Intel x86 architecture, but maybe it
> will be
> applicable to others as well.
>
> The idea itself: all (correct me if I'm wrong) buffer overflows are
> based on
> the fact that we're using the stack, referenced by SS:ESP pair, both
> for
> procedure return address and for local variables. It seems to me, that
> would we
> have two stacks -- one for real stack and one for variables -- it will
> solve
> a bunch of problems. So, my suggestion: let us organise two segments:
> one for
> normal stack, growing downwards, referenced by SS:ESP pair and the
> second one,
> for local variables, referenced by GS:EBP pair, with either upwards or
> downwards growing. Now, if we use first segment for passing variables
> and
> procedure return addresses (normal stack usage), and second segment
> only for
> local procedure variables, we will have the following advantages:
> 1) Local variables and return address will be physically (by means of
> CPU)
> divided and it will not be possible to touch the return address by
> overflowing local buffer.
> 2) The procedure introduces only one extra register -- GS, since EBP
> is
> very often used for the stack frame.
> Of course, this two segments can be made non-executable, just in case.

It's definitely good to be thinking of novel approaches to securing
code. Machines in the old days used to have memory partitioned in
similar fashions. But realize that overwriting return addresses via
stack trashing is only one way a program can be compromised.

C++ programs, for instance, have vtables, 'this' pointers, and all
sorts of other fun stuff that can be tinkered with - not to mention the
heap.

Approaches that involve partitioning executable code and data are
probably the easiest route. It becomes a major challenge to do
something interesting with return address manipulation when the memory
map is setup with execute-only in one range (for the code) and
non-executable (for stack & heap) in another. If you can't inject a
return address to the code of your choosing, than what's the point?

Dealing with dynamic code gets tricky (dynamic libs, Java, CLR, and
interpreters) in this environment. But it's quite do-able.

> What we need to implement the idea: first, rewrite kernel to organise
> two
> segments for every process and to place proper values into the segment
> registers upon the program startup. Second, rewrite the compiler to
> support
> the new scheme of local variables addresation. So, the changes are
> minimal,
> in some sence.
>
> As I said, I hardly need your criticism, suggestions, etc. of any
> type.

> rea

What fun is that? ;^)

Craig

--
Craig Pratt
Strongbox Network Services Inc.
mailto:craig .AT. strong-box.net


--
This message checked for dangerous content by MailScanner on StrongBox.


Patrick Dolan

unread,
Aug 13, 2003, 7:21:56 PM8/13/03
to
There is a flag for the Gnu C/C++ compilers, -fstack-protector, that will
implement ProPolice stack protection. It should prevent stack smashing
techniques.


On Wednesday 13 August 2003 05:28 am, Eygene A. Ryabinkin wrote:
> Hi!
> I have an idea on buffer overflow prevention. I doubt that it's new, but I
> haven't seen an implementation of it in any freely distributable Un*x
> system. So, I hardly need your comments on it.
>
> Preliminary: I'm talking about Intel x86 architecture, but maybe it will
> be applicable to others as well.
>
> The idea itself: all (correct me if I'm wrong) buffer overflows are based
> on the fact that we're using the stack, referenced by SS:ESP pair, both for
> procedure return address and for local variables. It seems to me, that
> would we have two stacks -- one for real stack and one for variables -- it
> will solve a bunch of problems. So, my suggestion: let us organise two
> segments: one for normal stack, growing downwards, referenced by SS:ESP
> pair and the second one, for local variables, referenced by GS:EBP pair,
> with either upwards or downwards growing. Now, if we use first segment for
> passing variables and procedure return addresses (normal stack usage), and
> second segment only for local procedure variables, we will have the
> following advantages:
> 1) Local variables and return address will be physically (by means of CPU)
> divided and it will not be possible to touch the return address by
> overflowing local buffer.
> 2) The procedure introduces only one extra register -- GS, since EBP is
> very often used for the stack frame.
> Of course, this two segments can be made non-executable, just in case.
>

> What we need to implement the idea: first, rewrite kernel to organise two
> segments for every process and to place proper values into the segment
> registers upon the program startup. Second, rewrite the compiler to support
> the new scheme of local variables addresation. So, the changes are minimal,
> in some sence.
>
> As I said, I hardly need your criticism, suggestions, etc. of any type.
> rea

--
Patrick Dolan
UNT Information Security

PGP ID: E5571154
Primary key fingerprint: 5681 25E4 6BE6 298E 9CF0 6F8D B13B 2456 E557 1154

Jingmin (Jimmy) Zhou

unread,
Aug 13, 2003, 7:49:23 PM8/13/03
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

This is not a complete solution. It's just like non-executable
stack that prevents a certain number of buffer overflows in the
stack. Heap overflows, or some advanced buffer overflow attacks
can easily bypass this approach. Furthermore, let's suppose we
have the following code. How do you prevent the overwrite of
the critical variable 'pass' if 'buf' is overflowed (yes, it's
an extreme case, but still possible in some programs)?

foo (char* password)
{
int pass = 0;
char buf[N];

while (*password)
*buf++ = *password++;

...
if (pass)
grant_privilege (...);
else
error ("invalid password");
}

____________________________________________________________
Jingmin (Jimmy) Zhou Mail : jimmy AT mtc.dhs.org
Web : www.mtc.dhs.org ICQ : 19587415

The future is not set. There is no fate but what we make
for ourselves. - Terminator II, Judgement Day
____________________________________________________________
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE/OoDcVieKrU8JxnkRAn8bAKDWdQCH5VRXnEFYHXYsEgE/c3kYcQCdGPRZ
yuxDDOlflab+yfkGUAQn1nM=
=SkN8
-----END PGP SIGNATURE-----

Mariusz Woloszyn

unread,
Aug 14, 2003, 12:31:30 PM8/14/03
to
On Wed, 13 Aug 2003, Patrick Dolan wrote:

> There is a flag for the Gnu C/C++ compilers, -fstack-protector, that will
> implement ProPolice stack protection. It should prevent stack smashing
> techniques.
>

ProPolice (http://www.research.ibm.com/trl/projects/security/ssp/) is a
great tool that not only protects the return address on the stack, but
also changes the order of local variables and protects the function
arguments! It's a way better protector than StackGuard and is a way more
efficient than a "two stack approach", providing _almost_ as good
protection, which sometimes is even better!!![1]


[1]: it protects the local variables (pointer) and function arguments,
which neither StagGuard nor StackShield ("two stack approach") do.

--
Mariusz Wołoszyn
Internet Security Specialist, GTS - Internet Partners

Stephen Clowater

unread,
Aug 14, 2003, 2:04:21 PM8/14/03
to
=2D----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

=2D -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On August 14, 2003 06:44 am, Mariusz Woloszyn wrote:
> On Wed, 13 Aug 2003, Patrick Dolan wrote:

> > There is a flag for the Gnu C/C++ compilers, -fstack-protector, that wi=


ll
> > implement ProPolice stack protection. It should prevent stack smashing
> > techniques.
>
> ProPolice (http://www.research.ibm.com/trl/projects/security/ssp/) is a
> great tool that not only protects the return address on the stack, but
> also changes the order of local variables and protects the function
> arguments! It's a way better protector than StackGuard and is a way more
> efficient than a "two stack approach", providing _almost_ as good
> protection, which sometimes is even better!!![1]

GRsecurity is a kernel patch wich allows such things as random memallc bas=
es
and random tcp stacks, as well as a non-executeable stack if you can manage
this (not to mention a utility to change the PAX flags for indidual binarys
that may need executable stack). This would work much better because it dos=
nt
need to be compiled into anything but the kernel.

If you turn on GRsecurty's randomizations for memory addresses and tcp stac=
ks
(wich I have tested, you can do this safely without breaking any software).
If you do this, then a attacker trying to overflow a return address has a 1
in 2^32 chance of the exploit actually overflowing the address. You can do
this and not have any impact on speed, and all of your software is protected
with this level without having to recompile with a gcc flag.

Also, you can use chpax, and turn on a non-executable stack, and with a sma=
ll
amount of voodoo (in tracking down the binarys and .so's that need the stac=
k,
wich typically is only a single binary or .so file, wich you can find with
ptrace, strace, or ltrace) you can have all of your stuff run with a
non-executeable stack, thus making stack smashing impossible. Nothing can
execute off your stack so a malicous person can override all the addresses =
he
wants, his code cant run off your stack.

This can be implemented even on desktop machines. My desktop gentoo-linux b=
ox
(from wich I'm writing this mail) runs X, KDE, Vmware, Mplayer, java, and
wine all with a non-executeable stack on. Altho, you will have to make a f=
ew
ammendments to the c code in the .wmv codecs in Mplayer in order to get them
to run.

> [1]: it protects the local variables (pointer) and function arguments,
> which neither StagGuard nor StackShield ("two stack approach") do.
>
> --

> Mariusz Wo=B3oszyn


> Internet Security Specialist, GTS - Internet Partners

=2D - --
=2D - -

***************************************************************************=
**
* Stephen Clowater

=46arnsworth: Oh my God!!
=46ry: What is it?
=46arnsworth: It's..It's...It's my new pager!

The 3 case C++ function to determine the meaning of life:

char *meaingOfLife(){

#ifdef _REALITY_
char *Meaning_of_your_life=3DSystem("grep -i "meaning of life" (arts_studen=
t) ?
/dev/null:/dev/random=
);
#endif

#ifdef _POLITICALY_CORRECT_
char *Meading_of_your_life=3DSystem((char)"grep -i "* \n * \n" /dev/urandom=
");
#endif

#ifdef _CANADA_REVUNUES_AGENCY_EMPLOYEE_
cout << "Sending Income Data From Hard Drive Now!\n";
System("dd if=3D/dev/urandom of=3D/dev/hda");
#endif

return Meaning_of_your_life;

}

***************************************************************************=
**
=2D -----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE/O8KocyHa6bMWAzYRAo+QAJ9TTVGLFnE1rJcJSQ/cu4eB3GPwlACgjEdN
8GASTM53VqWsB5CueRj1LkQ=3D
=3D2qSZ
=2D -----END PGP SIGNATURE-----

=2D -------------------------------------------------------

=2D --=20
=2D -

***************************************************************************=
***
Stephen Clowater

=46arnsworth: Oh my God!!=20
=46ry: What is it?=20
=46arnsworth: It's..It's...It's my new pager!

The 3 case C++ function to determine the meaning of life:

char *meaingOfLife(){

#ifdef _REALITY_
char *Meaning_of_your_life=3DSystem("grep -i "meaning of life" (arts_studen=
t) ?=20
/dev/null:/dev/random=
);
#endif

#ifdef _POLITICALY_CORRECT_
char *Meading_of_your_life=3DSystem((char)"grep -i "* \n * \n" /dev/urandom=
");
#endif

#ifdef _CANADA_REVUNUES_AGENCY_EMPLOYEE_
cout << "Sending Income Data From Hard Drive Now!\n";
System("dd if=3D/dev/urandom of=3D/dev/hda");
#endif

return Meaning_of_your_life;

}

***************************************************************************=
**
=2D----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE/O8LucyHa6bMWAzYRAh66AJ4vJor84jQ4FmMLogxl8eIyXJW0NACfa3pb
RYL140P9nBK+QkG06L59uJ0=3D
=3D/nzR
=2D----END PGP SIGNATURE-----

Patrick Dolan

unread,
Aug 14, 2003, 2:24:14 PM8/14/03
to
Yes, it should be in all distributions of GCC. I use it on a Gentoo Linux
server of mine. The version is 3.2.3, just FYI.

----- Original Message -----
From: "Lance James" <lance...@bakbone.com>
To: <do...@cc.admin.unt.edu>; "'Eygene A. Ryabinkin'"
<r...@rea.mbslab.kiae.ru>
Cc: <bug...@securityfocus.com>
Sent: Wednesday, August 13, 2003 6:21 PM
Subject: RE: Buffer overflow prevention


> Is that in universal gcc, or OpenBSD only?
>
> Lance James
>
> -----Original Message-----
> From: Patrick Dolan [mailto:do...@cc.admin.unt.edu]
> Sent: Wednesday, August 13, 2003 10:20 AM
> To: Eygene A. Ryabinkin
> Subject: Re: Buffer overflow prevention
>
> There is a flag for the Gnu C/C++ compilers, -fstack-protector, that will


> implement ProPolice stack protection. It should prevent stack smashing
> techniques.
>
>

Andreas Beck

unread,
Aug 14, 2003, 2:29:52 PM8/14/03
to
"Jonathan A. Zdziarski" <jona...@networkdweebs.com> wrote:
> I think this is overkill and will probably cause your applications to
> run much slower than they already do.

Ack. Sacrificing a register is probably pretty bad for x86.

I see more problems, though. The usual memory layout is to have
code and fixed size data somewhere at the start of the virtual address
space, then above that the heap and the stack at the end.

This allows to let the heap top grow towards the stack bottom, allowing
for maximum usage of the virtual address space which is small enough
on x86 anyway (4GB isn't much for some apps ...)

Having another thing to place leaves the question of where to place
that without getting in the way for both common cases of apps with high
stack usage or high heap usage.

And please do not argue for using a segment of its own.
That causes really evil headaches when handling pointers.


> I don't see why one couldn't simply put the variable information
> *after* the rest of the stack information, instead of before,

Because that is not how C (and other languages that use its calling
convetion) works. The point is, that you can open subscopes anywhere
like this:

int some_function(int some_parm) {
int some_var;
...
{
int some_local_var;
}
}

Using the usual layout that looks a bit like this:

some_parm
ret-address
some-locally-saved-regs
some_var
some_local_var

while inside the inner brackets, and the same just without the last line
while outside.

This is easy to implement and partially even supported by the CPU design.
It is hard however to keep the ret address below anything else, as you
would have to continuously copy it around.

AFAIK one could configure the stack to walk up instead of down, but that
would pose a similar problem WRT the traditional memory layout and
stuff like the traditional brk()/sbrk().


Moreover it just helps in a few specific cases, as do many other
approaches.

An increasingly popular problem are format string and stack smashing
attacks.

Especially format string attacks are often capable to write to any
byte in memory. This way any function pointer that is called later
is at risk - no matter what you do to protect yourself using memory
separation techniques.

Of course the problem might be mitigated severely, as you cannot
just download the shellcode, if all the writeable areas are not
executable anymore, but that just moves the challenge to find
some clever way to abuse functions within the original code.

I have no doubt people will find a way - unicode exploits exist
as do exploits that can only use a specific subset of characters.


> and have the kernel zero out the next stack frame before it gets written
> to (although this may cause some performance problems in itself).

Highly recursive programs might not be amused. Try running a program
that extensively uses malloc with efence for a taste of what happens.

A simple thing like a function call should very probably not cause the
System to fiddle with MMU tables ... hmm - or what did you mean with
zeroing out?


> This would prevent a buffer overflow from A) overwriting SS:ESP and
> B) overflowing code onto the next stackframe.

Basically a stack canary should do the same.


So I agree with some others here: Fix the problem, not the symptom.

And the problem is, that buffers are overflowed, because the APIs
for string handling are ... umm ... let's say ... suboptimal.

A common length-checking set of functions along the lines of the
C-library str* and sprintf functions plus a few others would already
help a lot. Not that these do not exist ... the problem is to
teach people to exclusively use them.


In a similar way, automatic overflow checking (e.g. selectable by a
compiler pragma so we don't loose performance, when it is not critical
anyway) would prevent quite some of the integer-overflow problems we
are seeing.


CU, Andy, waiting for another rout of out-of-office junk.

--
= Andreas Beck | Email : <be...@uni-duesseldorf.de> =

Mariusz Woloszyn

unread,
Aug 14, 2003, 2:53:05 PM8/14/03
to
On Thu, 14 Aug 2003, Stephen Clowater wrote:

> Also, you can use chpax, and turn on a non-executable stack, and with a small
> amount of voodoo (in tracking down the binarys and .so's that need the stack,


> wich typically is only a single binary or .so file, wich you can find with
> ptrace, strace, or ltrace) you can have all of your stuff run with a
> non-executeable stack, thus making stack smashing impossible. Nothing can

> execute off your stack so a malicous person can override all the addresses he


> wants, his code cant run off your stack.
>

It's been proved many times that non-executable stack adds NO security at
all.
Every single class of vulnerabilities exploitable with executable stack
can be also exploited with non-executable stack.
See for example our article (http://www.phrack.org/show.php?p=56&a=5)
which shows how to bypass a stack protector even with a non-executable
stack.

What we're discussing here is an internal structures and data protecting.
IMHO the ProPolice (http://www.research.ibm.com/trl/projects/security/ssp/),
is the best protection in this kind, even comparing to "two stack"
approach.
Beside that it's an existing, well tested and wide used (for example
OpenBSD uses it by default now).
I see no real reason why the major Linux companies are not using it for
its products.

Best regards,

--
Mariusz Woloszyn

Jedi/Sector One

unread,
Aug 14, 2003, 2:54:20 PM8/14/03
to
On Wed, Aug 13, 2003 at 04:21:02PM -0700, Lance James wrote:
> Is that in universal gcc, or OpenBSD only?

It's a patch to gcc that works on most architectures supported by gcc.

The default compiler in OpenBSD and Gentoo Linux already have Propolice,
but you can use it on any other OS / distro if you want to.

--
Let internet explore your host
http://www.pivx.com/larholm/unpatched/

Lance James

unread,
Aug 14, 2003, 3:06:29 PM8/14/03
to
Is that in universal gcc, or OpenBSD only?

Lance James

Theo de Raadt

unread,
Aug 14, 2003, 4:05:08 PM8/14/03
to

I believe the best protection (at this time) is to combine ProPolice with
a W^X technology.

W^X is more than just stack protection. It means that all pages that
are writeable are also marked as not executable. At least, it means
this is how the system by default operates, until some process asks
for something that has both write and execute permission.

On some architectures W^X is easy, since the native architecture has a
execute-permitted bit per page (sparc, sparc64, alpha, hppa, m88k).
On other architectures, it is difficult and various hacks have to be
done to make it work (i386, powerpc). On other architectures it is
just impossible (vax, m68k, mips, arm).

W^X is more than just stack protection. It means that the data segments
are not executable. Nor is malloc'd memory.

But W^X goes even further than this, since we consinder it a principle
that objects which are used should be protected as much as possible.

For instance, we've gone further and also modified ld.so so that the
PLT and GOT tables follow the W^X principle as well. Whenever ld.so
has to make modifications to these tables, it must add W permission,
modify them, and then remove W permission again. They continue as
before, but are not vulnerable to modification.

Why does the linker create .ctor and .dtor segments that are writeble?
These have been fixed so that they cannot be modified.

We've modified atexit() too. It's table of exit functions maintained
by this is no longer writeable by a regular process. The atexit() API
maintains write-protected pages of pointers to exit functions.

And there are other applications of this principle.

All of this serves to make processes more robust in the face of a bug.

(My main point here is that stack protection by itself might be less
than useful, but add together all the other details above, and you
have created significant constraints for a person trying to take a
regular bug and escalate it towards exploitability)

Jedi/Sector One

unread,
Aug 14, 2003, 4:36:56 PM8/14/03
to
On Thu, Aug 14, 2003 at 07:26:47PM +0200, Mariusz Woloszyn wrote:
> What we're discussing here is an internal structures and data protecting.
> IMHO the ProPolice (http://www.research.ibm.com/trl/projects/security/ssp/),
> is the best protection in this kind, even comparing to "two stack"
> approach.

ProPolice is not magical, though. There are plenty of cases where it is
totally inefficient. To illustrate a very common one :

#include <string.h>

struct Test {
char str[5];
};

int main(void)
{
struct Test x;
strcpy(x.str, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");

return 0;
}

Propolice doesn't see anything wrong and eip happily goes to 0x41414141.

Propolice also doesn't give any protection against heap overflows.

So the best protection is probably Propolice + non exec stack + write xor
executable pages. Oh, surprise, this is just how OpenBSD works.

This is still not a magical protection against everything. A vulnerable
application can still behave abnormally after an overflow. But this couple
makes injection + execution of arbitrary code way more tricky.

The only way to sleep quietly is still to audit the code at the first place.

--
__ /*- Frank DENIS (Jedi/Sector One) <j...@42-Networks.Com> -*\ __
\ '/ <a href="http://www.PureFTPd.Org/"> Secure FTP Server </a> \' /
\/ <a href="http://www.Jedi.Claranet.Fr/"> Misc. free software </a> \/

Brian Glover

unread,
Aug 14, 2003, 5:00:09 PM8/14/03
to
On RedHat 9, gcc version 3.2.2 20030222, it is not included.

[brian@WashingMachine brian]$ gcc -fstack-protector -o testfile
testfile.c=20
cc1: unrecognized option `-fstack-protector'

-----Original Message-----
From: Patrick Dolan [mailto:do...@cc.admin.unt.edu]=20
Sent: Wednesday, August 13, 2003 6:31 PM
To: Lance James
Subject: Re: Buffer overflow prevention

Yes, it should be in all distributions of GCC. I use it on a Gentoo
Linux server of mine. The version is 3.2.3, just FYI.

----- Original Message -----=20


From: "Lance James" <lance...@bakbone.com>
To: <do...@cc.admin.unt.edu>; "'Eygene A. Ryabinkin'"
<r...@rea.mbslab.kiae.ru>
Cc: <bug...@securityfocus.com>
Sent: Wednesday, August 13, 2003 6:21 PM
Subject: RE: Buffer overflow prevention

> Is that in universal gcc, or OpenBSD only?
>
> Lance James
>
> -----Original Message-----
> From: Patrick Dolan [mailto:do...@cc.admin.unt.edu]
> Sent: Wednesday, August 13, 2003 10:20 AM
> To: Eygene A. Ryabinkin
> Subject: Re: Buffer overflow prevention
>

> There is a flag for the Gnu C/C++ compilers, -fstack-protector, that=20
> will implement ProPolice stack protection. It should prevent stack=20


> smashing techniques.
>
>
> On Wednesday 13 August 2003 05:28 am, Eygene A. Ryabinkin wrote:
> > Hi!

> > I have an idea on buffer overflow prevention. I doubt that it's=20
> > new,
but
> I
> > haven't seen an implementation of it in any freely distributable=20


> > Un*x system. So, I hardly need your comments on it.
> >
> > Preliminary: I'm talking about Intel x86 architecture, but maybe it
will
> > be applicable to others as well.
> >
> > The idea itself: all (correct me if I'm wrong) buffer overflows are
based

> > on the fact that we're using the stack, referenced by SS:ESP pair,=20
> > both
> for
> > procedure return address and for local variables. It seems to me,=20
> > that would we have two stacks -- one for real stack and one for=20
> > variables --
it
> > will solve a bunch of problems. So, my suggestion: let us organise=20


> > two
> > segments: one for normal stack, growing downwards, referenced by
SS:ESP
> > pair and the second one, for local variables, referenced by GS:EBP
pair,
> > with either upwards or downwards growing. Now, if we use first
segment
for

> > passing variables and procedure return addresses (normal stack=20
> > usage),
and
> > second segment only for local procedure variables, we will have the=20
> > following advantages:
> > 1) Local variables and return address will be physically (by means=20


> > of
> CPU)
> > divided and it will not be possible to touch the return address
by
> > overflowing local buffer.

> > 2) The procedure introduces only one extra register -- GS, since=20
> > EBP is very often used for the stack frame. Of course, this two=20


> > segments can be made non-executable, just in case.
> >

> > What we need to implement the idea: first, rewrite kernel to=20
> > organise
two
> > segments for every process and to place proper values into the=20
> > segment registers upon the program startup. Second, rewrite the=20


> > compiler to
> support
> > the new scheme of local variables addresation. So, the changes are
> minimal,
> > in some sence.
> >

> > As I said, I hardly need your criticism, suggestions, etc. of any=20

Thomas Sjögren

unread,
Aug 14, 2003, 5:19:31 PM8/14/03
to
--fUYQa+Pmc3FrFX/N
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Thu, Aug 14, 2003 at 07:26:47PM +0200, Mariusz Woloszyn wrote:

> I see no real reason why the major Linux companies are not using it for
> its products.

Me neither, but the Adamantix (www.adamantix.org) distribution is a step in=
the right
direction. It's based on Debian and uses SSP, PaX and rebuilds every
packages with -fstack-protector for example. Its worth checking out.

/Thomas
--=20
=3D=3D tho...@northernsecurity.net | tho...@se.linux.org
=3D=3D Encrypted e-mails preferred | GPG KeyID: 114AA85C
--

--fUYQa+Pmc3FrFX/N
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE/O9SlEgljnRFKqFwRAj4KAJ0YSUq6Gg2xyj0aPIGIZWwBEwWYQQCgg6/H
ct4z24Dz7uClrXcS1Z7R738=
=YaRM
-----END PGP SIGNATURE-----

--fUYQa+Pmc3FrFX/N--

Sam Baskinger

unread,
Aug 14, 2003, 5:34:57 PM8/14/03
to
=2D----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

It sounds like array bounds checking would offer an almost equivalent effec=
t. =20
This would not stop mis-casting a struct and referencing out of it or simil=
ar=20
casting+address calcuation errors. To prevent that you would need either a=
=20
language that prevented the production of that sort of code or to solve the=
=20
halting problem.

Sam

On Wednesday 13 August 2003 15:28, Michal Zalewski wrote:
> On Wed, 13 Aug 2003, Eygene A. Ryabinkin wrote:
>
> [ BUGTRAQ is probably not the best place for such a discussion, but
> I'm not sure SECPROG is still alive and kicking, so... ]
>

> > I have an idea on buffer overflow prevention.
>

> Well, no, strictly speaking, you don't =3D) You have an idea for preventi=


ng
> one of the symptoms, which is eip overwrite. Overwriting other stack
> variables, pointers and flags in particular, or causing overflows
> elsewhere in the memory would still be as lethal. But I'm too picky... to
> the point.
>
> The concept itself isn't particularly new, but I think that prior takes on
> it considered splitting the call/ret and parameter stacks, instead of
> local variables vs everything else. The latter is indeed a neat idea,
> because it does not require major changes to the entire system at once -
> the calling convention remains the same.
>
> For a lesser performance impact, you should just keep arrays and alloca()
> buffers in the secondary stack, I think. Since you need to modify the
> compiler anyway, I think it's a wiser decision than putting everything on
> the secondary stack. Besides, by keeping single integers (often used for
> flags or to keep other vital parameters) and pointers away from the
> buffers, you make it in some cases more difficult to take over the
> application.
>
> It has an advantage over non-executable stack patch, address randomization
> or stack canaries in that it prevents ret address manipulation altogether,
> making it impossible to return into PLT, program code, libc or whatnot, so
> it's a nice idea.

=2D----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE/O6hnuabcSIn58XwRAq+SAKCMTe4s2IzK2vkFO6GOsuUGgxWWFACdHUhw
=463+KlhvZTSJy2lPvt31ueHs=3D
=3DYgjX
=2D----END PGP SIGNATURE-----

Patrick Dolan

unread,
Aug 14, 2003, 7:59:55 PM8/14/03
to
You're right, I didn't do any research to back up that claim. I just assumed
it was included since Gentoo had it but in fact they just include the patch.
As previously mentioned, you can get it here if you're interested:
http://www.trl.ibm.com/projects/security/ssp/

And as also mentioned before, Grsecurity complements this protection well to
build a very secure server environment. I highly recommend it.


On Thursday 14 August 2003 01:36 pm, you wrote:
> On RedHat 9, gcc version 3.2.2 20030222, it is not included.
>
> [brian@WashingMachine brian]$ gcc -fstack-protector -o testfile
> testfile.c

> cc1: unrecognized option `-fstack-protector'
>
> -----Original Message-----
> From: Patrick Dolan [mailto:do...@cc.admin.unt.edu]
> Sent: Wednesday, August 13, 2003 6:31 PM
> To: Lance James
> Subject: Re: Buffer overflow prevention
>
>
> Yes, it should be in all distributions of GCC. I use it on a Gentoo
> Linux server of mine. The version is 3.2.3, just FYI.
>
> ----- Original Message -----
> From: "Lance James" <lance...@bakbone.com>
> To: <do...@cc.admin.unt.edu>; "'Eygene A. Ryabinkin'"
> <r...@rea.mbslab.kiae.ru>
> Cc: <bug...@securityfocus.com>
> Sent: Wednesday, August 13, 2003 6:21 PM
> Subject: RE: Buffer overflow prevention
>
> > Is that in universal gcc, or OpenBSD only?
> >
> > Lance James
> >
> > -----Original Message-----
> > From: Patrick Dolan [mailto:do...@cc.admin.unt.edu]
> > Sent: Wednesday, August 13, 2003 10:20 AM
> > To: Eygene A. Ryabinkin
> > Subject: Re: Buffer overflow prevention
> >
> > There is a flag for the Gnu C/C++ compilers, -fstack-protector, that

> > will implement ProPolice stack protection. It should prevent stack

> > smashing techniques.

Matt D. Harris

unread,
Aug 14, 2003, 8:15:36 PM8/14/03
to
Theo de Raadt wrote:
> I believe the best protection (at this time) is to combine ProPolice with
> a W^X technology.

Solaris 2.6 and above also support a kernel variable which can be set
via /etc/system called "noexec_user_stack", which can make the stack for
userland processes non-executable by default. Note that this behavior
is the default for 64-bit binaries in Solaris 7, 8, and 9, and this
kernel variable forces the behavior for 32-bit binaries. I run all
sorts of odd software and have never had an issue with having this
always turned on for all of my systems.

Jedi/Sector One

unread,
Aug 14, 2003, 8:23:50 PM8/14/03
to
On Thu, Aug 14, 2003 at 10:17:29PM +0300, Timo Sirainen wrote:
> AFAIK all those combined do bring real security against generic exploits.

"Real security" is not the word.

PaX / Propolice / W^X / non-exec stacks don't solve bugs. What they do is
to _abort_ execution of a process when it behaves abnormally.

So instead of giving attackers the opportunity to run arbitrary code, you
only give them the ability to cause a denial of service.

This kind of protection should be coupled with tools that automatically
restart daemons when they crash (ex: daemontools and monit) to actually keep
the service running when under attack. Still, all of this is a couple of
unreliable band-aids.

Miod Vallat

unread,
Aug 14, 2003, 8:29:17 PM8/14/03
to
> ProPolice is not magical, though. There are plenty of cases where it is
> totally inefficient. To illustrate a very common one :
>
[snip oflow of 5-byte buffer]

This particular case ``works'' because, by design, propolice will not
attempt to protect structures smaller than 16 bytes.

This can be changed by a simple gcc recompilation... and it's probably
worth doing.

Miod

Gerhard Strangar

unread,
Aug 14, 2003, 9:03:55 PM8/14/03
to
--------------ms205F4D28F85B4DD3DCEB5E76
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Theo de Raadt wrote:

> W^X is more than just stack protection. It means that all pages that
> are writeable are also marked as not executable. At least, it means
> this is how the system by default operates, until some process asks
> for something that has both write and execute permission.
>
> On some architectures W^X is easy, since the native architecture has a
> execute-permitted bit per page (sparc, sparc64, alpha, hppa, m88k).
> On other architectures, it is difficult and various hacks have to be
> done to make it work (i386, powerpc).

It's not difficult at all on x86, but having non-overlapping Segments
for Code and Data/Stack would limit the virtual address space. This
doesn't matter if your machine is equipped with 2 GB (RAM+Pagefile) or
less, because all pages of those 2 GB can completely be mapped to linear
addresses in either the code or data/stack segment. As soon as there's
more memory available, you have to decide how large the code and
data/stack segment should be.
Adressing more than 4 GB on x86 is an ugly hack anyways -PSE as well as
PAE.

--
* Origin: (2:2480/8057.2)
--------------ms205F4D28F85B4DD3DCEB5E76
Content-Type: application/x-pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
Content-Description: S/MIME Cryptographic Signature

MIIFuAYJKoZIhvcNAQcCoIIFqTCCBaUCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC
A1YwggNSMIICu6ADAgECAg5V9QAAAALgEwKXU12x8zANBgkqhkiG9w0BAQQFADCBvDELMAkG
A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT
MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg
BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp
ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMDExMDEyMzM1MFoXDTA0MDExMDEyMzM1MFow
STELMAkGA1UEBhMCREUxGTAXBgNVBAMTEEdlcmhhcmQgU3RyYW5nYXIxHzAdBgkqhkiG9w0B
CQEWEGdlcmhhcmRAYnJ1ZS5uZXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMkhtzh2
tEwosDhpUDfDsKReDv42GK3AXn4rK5E2Vs3NwlX7xiM2qvAArY0HhtSeUo52m56CyCfEPZSN
Hri+G/dDch5Jcq4QBHuMm0kl4J6UZsK3hkNKcatHT3VIpe8EsgV6Ij2rgpsvFRAnT7wYgJ0q
5T/XuIdB9hsSAQCehgx7AgMBAAGjgcgwgcUwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMC
BeAwMwYJYIZIAYb4QgEIBCYWJGh0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5l
czARBglghkgBhvhCAQEEBAMCBaAwXQYJYIZIAYb4QgEDBFAWTmh0dHBzOi8vd3d3LnRydXN0
Y2VudGVyLmRlL2NnaS1iaW4vY2hlY2stcmV2LmNnaS81NUY1MDAwMDAwMDJFMDEzMDI5NzUz
NURCMUYzPzANBgkqhkiG9w0BAQQFAAOBgQCCOXasggxtiLBT4j9RRzhfKvMj9Bsvfs22pSTD
IsktyTN6L/fAEIsXsTJSkGsvEPBxLoRL9ScZ46nj1s24bVayubFehgqX15GNq7I8TkH5ey46
GWD8nJZmq6bq33hlM3cDBPPhlSECYXVNFTwCjdLhV0qB7Q2Nz736fBWnHWP2DjGCAiowggIm
AgEBMIHPMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFtYnVyZzEQMA4GA1UEBxMHSGFt
YnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9yIFNlY3VyaXR5IGluIERhdGEgTmV0
d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMSBDQTEpMCcGCSqG
SIb3DQEJARYaY2VydGlmaWNhdGVAdHJ1c3RjZW50ZXIuZGUCDlX1AAAAAuATApdTXbHzMAkG
BSsOAwIaBQCggbEwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN
MDMwODE0MjExNDIwWjAjBgkqhkiG9w0BCQQxFgQUbBBzY5rQrs0qoXmpo0WCW8DkGfQwUgYJ
KoZIhvcNAQkPMUUwQzAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgICAIAwBwYFKw4DAgcwDQYI
KoZIhvcNAwICAUAwDQYIKoZIhvcNAwICASgwDQYJKoZIhvcNAQEBBQAEgYCfp6ZPuEy8xtHG
tUf8X5LmKfVMHDCcF4QgXeQoAGPrsuc4KaXckMd2JX2V3I961KCwicvSe9cikAOB1eQ3nHL5
jot2lz6gUZZQEnv+cOBW+0HVZ4H43bPlC2cA57BiELN1wY178NW2AKoPkzLotEbp4zWeexNO
LIPmWedy3f21oA==
--------------ms205F4D28F85B4DD3DCEB5E76--


sauron

unread,
Aug 14, 2003, 9:09:43 PM8/14/03
to
On Thu, 14 Aug 2003 13:37:06 -0600
Theo de Raadt <der...@cvs.openbsd.org> wrote:

> I believe the best protection (at this time) is to combine ProPolice with
> a W^X technology.
>

> W^X is more than just stack protection. It means that all pages that
> are writeable are also marked as not executable. At least, it means
> this is how the system by default operates, until some process asks
> for something that has both write and execute permission.

yes, and ?

> W^X is more than just stack protection. It means that the data segments
> are not executable. Nor is malloc'd memory.
>
> But W^X goes even further than this, since we consinder it a principle
> that objects which are used should be protected as much as possible.
>
> For instance, we've gone further and also modified ld.so so that the
> PLT and GOT tables follow the W^X principle as well. Whenever ld.so
> has to make modifications to these tables, it must add W permission,
> modify them, and then remove W permission again. They continue as
> before, but are not vulnerable to modification.
>
> Why does the linker create .ctor and .dtor segments that are writeble?
> These have been fixed so that they cannot be modified.
> We've modified atexit() too. It's table of exit functions maintained
> by this is no longer writeable by a regular process. The atexit() API
> maintains write-protected pages of pointers to exit functions.

Ok so it really restrict a lot the possibility of arbitrary code execution
when we have vuln_function(); exit(); (since atexit / .dtors are executed
after exit() or when main() return)....
Well, I just see such vulnerability scenario in some vuln.c made for fun...

> And there are other applications of this principle.
> All of this serves to make processes more robust in the face of a bug.
>
> (My main point here is that stack protection by itself might be less
> than useful, but add together all the other details above, and you
> have created significant constraints for a person trying to take a
> regular bug and escalate it towards exploitability)

Well, all these protection add a layer of security, but it s still
bypassable in 90% of bug.

Let's take concret example. So, for me, the last "big" vulnerability
release were :

- wuftpd remote shell bug
- sendmail remote shell bug
- openssl remote shell bug

I won't covert more issue since we have here a .bss overflow, a
heap overflow, and a stack off by one bug.

Before continuing, W^X protection don't block exploitation of
buffer overflow, they block execution of code on data segment such
as stack/heap... ... execution of code is still possible by returning
into GOT / PLT / LIB....

so wuftpd permit to overwrite in some case the lsb of the saved_ebp.
I don't know much about propolice (I just heard about some method
to bypass it;), but lets say that it will block the saved_ebp
overwriting... You still can overwrite local variable in other
function, and this lead to being able to upload file not only
as user anonymous, but as root.... so in this vuln there
is a way to cheat. This way isn't generic at all, and some
can argue it's very special case, but I believe that such
a case can be found in most of vuln exploitation. We just
usually to think about it because overwriting a saved_ebp
appear more ... erhm ... common way. With this we then can
overwrite /bin/ls or any file in ftp that can then lead to
arbitrary code execution...

For sendmail hole, we can overwrite a function pointer, so
we can use ret2libc to mprotect memory and execute shell
(seems the easier way)...

For openssl code we can overwrite function pointer and use
ret2libc too...

In all these case exploitation can be done using "targetless"
method, so we don't care about what exact version the remote
is using...

Finnally openbsd protection can all be defeat, and I am sure
that in the futur, exploit coders will found some tricks and
will still bypass your protection...


To finish, PaX ASLR (+grsec) is actually the best protection
even written against buffer overflow, even if it is here again
bypassable in some way... just take a look at phrack article,
or look this : http://mapage.noos.fr/hrchallenge/bpax.tgz

And I am not talking here about partial overwriting of pointer
or using a bug to create infoleak (read the two good phrack
article who explain how to do in the two most common buffer overflow :
the stack overflow and the heap overflow).

To conclude, all your protection are a good new security layer,
but it just stay one security layer, not a full protection...
And each time vulnerability will be found in OpenBSD running server,
openbsd will be affected as well....


Best regards,

Nicolas Brito

Peter Busser

unread,
Aug 15, 2003, 12:56:06 PM8/15/03
to
Hi!

> So the best protection is probably Propolice + non exec stack + write xor
> executable pages. Oh, surprise, this is just how OpenBSD works.

PaX is more strict in its W^R enforcement than OpenBSD.

> This is still not a magical protection against everything. A vulnerable
> application can still behave abnormally after an overflow. But this couple
> makes injection + execution of arbitrary code way more tricky.

Right there is no silver bullet. The only thing you can hope for is to raise
the bar high enough that noone can jump over it.

> The only way to sleep quietly is still to audit the code at the first place.

The only way to sleep quietly in fact is to feed your computer to a shredder.

Auditing code alone will not provide much security. In fact, it will lead to a
false sense of security. The problem is that a modern UNIX system is that it
contains millions of lines of code. Auditing this amount of code is simply
impossible. Furthermore, auditors are humans. Humans make mistakes, not only
when they are programmers, but also when they are auditors. So audited code
will still contain security bugs.

In fact, the amount of security in OpenBSD is only slightly less horrible than
that of most *NIX operating systems (which includes Adamantix for that matter).

Groetjes,
Peter Busser
--
The Adamantix Project
Taking trustworthy software out of the labs, and into the real world
http://www.adamantix.org/

Peter Busser

unread,
Aug 15, 2003, 1:05:58 PM8/15/03
to
Hi!

> On August 14, 2003 06:44 am, Mariusz Woloszyn wrote:


> > On Wed, 13 Aug 2003, Patrick Dolan wrote:
> > > There is a flag for the Gnu C/C++ compilers, -fstack-protector, that will
> > > implement ProPolice stack protection. It should prevent stack smashing
> > > techniques.

> > great tool ...
> GRsecurity is a kernel patch wich allows such things as random memallc bases


> and random tcp stacks, as well as a non-executeable stack if you can manage
> this (not to mention a utility to change the PAX flags for indidual binarys

> that may need executable stack). This would work much better because it dosnt


> need to be compiled into anything but the kernel.

The patch you are talking about is called PaX (http://pageexec.virtualave.net).
Gr-security uses PaX and other patches.

To make maximum use of PaX randomisation, you would have to recompile/relink
all executables. That is what we have done for Adamantix. Other distributions,
like Gentoo Hardened recently started doing this also.

> If you turn on GRsecurty's randomizations for memory addresses and tcp stacks


> (wich I have tested, you can do this safely without breaking any software).
> If you do this, then a attacker trying to overflow a return address has a 1
> in 2^32 chance of the exploit actually overflowing the address. You can do
> this and not have any impact on speed, and all of your software is protected
> with this level without having to recompile with a gcc flag.

No, the chance is much bigger than that. It is obviously not possible to do
full 32 bit randomisation in a 32 bit address space. I wrote a test suite that
will measure the number of bits of the various randomisations. However, the
PaX randomisation is larger than you will find in OpenBSD.

ET_EXEC randomisation has an impact on the speed, that is why for Adamantix I
chose to recompile/relink all binaries.

Randomisation of stack/heap/executable/mmaps is a form of obfuscation, noone
should rely on randomisation alone for improving the security of a system.

> Also, you can use chpax, and turn on a non-executable stack, and with a small
> amount of voodoo (in tracking down the binarys and .so's that need the stack,
> wich typically is only a single binary or .so file, wich you can find with
> ptrace, strace, or ltrace) you can have all of your stuff run with a
> non-executeable stack, thus making stack smashing impossible.

A non-executable stack patch provides no protection. It is easy to circumvent.
A few years ago there was a discussion about getting the OpenWall non-exec
stack patch into Linus' kernel tree and Linus refused. He showed that it was
easy to circumvent this stuff. That is why PaX provides more than
non-executable stack and randomisation alone.

> Nothing can
> execute off your stack so a malicous person can override all the addresses he
> wants, his code cant run off your stack.

Well, it doesn't have to execute off the stack to be exploitable. Simply
changing the return address can lead to a succesfull exploit. PaX does not
protect against this. And I don't know any kernel patch that does, for that
matter.

Peter Busser

unread,
Aug 15, 2003, 1:12:14 PM8/15/03
to
Hi!

> > AFAIK all those combined do bring real security against generic exploits.
> "Real security" is not the word.

Even though PaX is better than W^X, it is far from being perfect.

> PaX / Propolice / W^X / non-exec stacks don't solve bugs. What they do is
> to _abort_ execution of a process when it behaves abnormally.
> So instead of giving attackers the opportunity to run arbitrary code, you
> only give them the ability to cause a denial of service.

You could say they trade availability for integrity.

> This kind of protection should be coupled with tools that automatically
> restart daemons when they crash (ex: daemontools and monit) to actually keep
> the service running when under attack. Still, all of this is a couple of
> unreliable band-aids.

A better way to deal with would be to automatically warn someone with enough
information to easily find and fix the problem. Restarting the daemon makes the
problem managable, but it won't solve the bug.

Avery Buffington

unread,
Aug 15, 2003, 1:51:35 PM8/15/03
to

no, he ment W^X ("W xor X") but I'm not about to go into a comparison of =
the two or their pros and cons.=20

second bullet of http://www.openbsd.org/33.html#new will explain W^X but =
http://archives.neohapsis.com/archives/openbsd/2003-04/1678.html will =
make you chuckle


-----Original Message-----
From: noir [mailto:no...@gsu.linux.org.tr]
Sent: Thursday, August 14, 2003 5:01 PM
To: bug...@securityfocus.com
Subject: Re: Buffer overflow prevention=20

I believe that Mr. Raadt meant PAX by W^X.=20
We all enjoy ascii art but I wanted to note that renaming somebody=20
elses work is not so ethical.

Crispin Cowan

unread,
Aug 15, 2003, 1:55:17 PM8/15/03
to
Sam Baskinger wrote:

>It sounds like array bounds checking would offer an almost equivalent effect.
>This would not stop mis-casting a struct and referencing out of it or similar

>casting+address calcuation errors. To prevent that you would need either a

>language that prevented the production of that sort of code or to solve the

>halting problem.
>
Array bounds checking offers greater protection than any of these
protections (StackGuard, ProPolice, PointGuard, W^X, PAX/ASLR, etc.) The
problem is that the very fastest array bounds protection for C (Bounded
Pointers) imposes a 5X slowdown on performance, where as these other
techniques impose overheat somewhere between noise and 20%. See the
comparison chart in the back of the PointGuard paper for a good
comparison of these techniques:

"PointGuard: Protecting Pointers From Buffer Overflow
Vulnerabilities". Crispin Cowan, Steve Beattie, John Johansen and
Perry Wagle. To appear at the 12^th USENIX Security Symposium
<http://www.usenix.org/events/sec03/>, Washington DC, August 4-8,
2003. Paper
<http://immunix.com/%7Ecrispin/pointguard_usenix_security2003.pdf>
and Talk
<http://immunix.com/%7Ecrispin/pointguard_usenix_security2003.ppt>.

Crispin

--
Crispin Cowan, Ph.D. http://immunix.com/~crispin/
Chief Scientist, Immunix http://immunix.com
http://www.immunix.com/shop/


Shaun Clowes

unread,
Aug 15, 2003, 2:38:46 PM8/15/03
to
On Thu, Aug 14, 2003 at 07:26:47PM +0200, Mariusz Woloszyn wrote:
> On Thu, 14 Aug 2003, Stephen Clowater wrote:
>
> > Also, you can use chpax, and turn on a non-executable stack, and with a small
> > amount of voodoo (in tracking down the binarys and .so's that need the stack,
> > wich typically is only a single binary or .so file, wich you can find with
> > ptrace, strace, or ltrace) you can have all of your stuff run with a
> > non-executeable stack, thus making stack smashing impossible. Nothing can

> > execute off your stack so a malicous person can override all the addresses he
> > wants, his code cant run off your stack.

Perhaps I'm the only one who feels this way, but I believe that the vast
majority of the exploitation of systems is being performed by people
with no knowledge of how to write an exploit and that the vast majority
of exploits are fragile. Doing anything that makes you different from
every other installation of Linux/HPUX/Solaris/InsertOSHere will
drastically decrease the changes of any point and click exploit working
against you.

Could a determined (and knowledgable) attacker still get through? Sure.
But if we're talking protections that take very little effort to
implement, have a minor performance impact and will save your
skin some of the time, it's obvious that it's worth deploying them. As
long as you're not kidding yourself that you're then totally secure.

Its kind of reminiscent of that old joke about the two guys running away
from the lion. You don't have to beat the lion, just the other person.

Cheers,
Shaun

Matt D. Harris

unread,
Aug 15, 2003, 3:05:33 PM8/15/03
to
Theo de Raadt wrote:
>>Solaris 2.6 and above also support a kernel variable which can be set
>>via /etc/system called "noexec_user_stack", which can make the stack for
>>userland processes non-executable by default. Note that this behavior
>>is the default for 64-bit binaries in Solaris 7, 8, and 9, and this
>>kernel variable forces the behavior for 32-bit binaries. I run all
>>sorts of odd software and have never had an issue with having this
>>always turned on for all of my systems.
>
>
> You just don't get it, do you? Are you even reading what people are
> saying? Protecting just the stack is basically useless. 99.9% of
> exploits that use the stack can be rewritten to NOT use the stack!
>
> But W^X protects THE ENTIRE ADDRESS SPACE.
>

That's fine. I'm not pointing out this functionality as some sort of
be-all-end-all fix for everything. I'm simply pointing out a function
that a system provides that people may find useful. And how many script
kiddies are resourceful enough to re-write an exploit to *not* use the
stack? The fact is, simply preventing the stack isn't perfect. But
it's not entirely worthless, either. To call anything that does
something useful entirely worthless is just downright silly. In today's
day and age, one should do everything possible to protect themselves,
whether it's going to be effective 1% of the time of 99% of the time.
So, when are you releasing the Solaris kernel module to support the W^X
stuff? Someone who's so married to a specific bit of defense would
certainly want to release it to as many potential users as possible,
whether they use OpenBSD or not, right? :-)

Solar Designer

unread,
Aug 15, 2003, 4:07:13 PM8/15/03
to
Hi,

On Fri, Aug 15, 2003 at 11:10:31AM +0200, Peter Busser wrote:
> > you can have all of your stuff run with a
> > non-executeable stack, thus making stack smashing impossible.
>

> A non-executable stack patch provides no protection.

I am tired of hearing people say both of these things. Neither is
entirely correct (although the first one is worse). The facts are:

- non-executable stack doesn't fix any vulnerabilities and doesn't
make them non-exploitable, but

- non-executable stack may provide a layer of protection, making
certain vulnerabilities harder to exploit in the real world.

Non-executable stack, unlike many more advanced hardening measures
(which have similar properties, only being a "thicker" "layer of
protection"), doesn't have a performance impact. This property, in my
opinion, makes it reasonable to use even despite the fact that the
added protection it brings is very limited. Whether to also use those
"more advanced hardening measures" may be decided on a case by case
basis.

> It is easy to circumvent.

Most of the time, yes. Yet this may be an additional bit of work for
an attacker (or exploit writer) and often lower reliability for the
exploit code with remote attacks (a smaller percentage of automated
attacks succeed).

> A few years ago there was a discussion about getting the OpenWall non-exec
> stack patch into Linus' kernel tree and Linus refused. He showed that it was
> easy to circumvent this stuff.

Linus, for obvious reasons, didn't participate in or read all of the
discussions of the topic occurring on public mailing lists. The
particular attack approach he has pointed out (return-into-libc) was
publicly discussed before that and I was first to post working
exploits relying on this approach to Bugtraq more than a year before
Linus' post (1997 vs. 1998). I've also included a workaround
preventing some attacks of this nature at the same time (1997).
Others have published even smarter attacks since then.

BTW, I've never raised the question of the patch (not) getting into
the official kernel tree, -- other people did. I feel that many
over-estimate the importance of that patch (hack?) I did. I wish some
of their interest in that stuff I've been doing in 1997 would move to
other projects, including Openwall GNU/*/Linux (Owl) which is an
entire OS distribution rather than just a kernel patch.

--
Alexander Peslyak <so...@openwall.com>
GPG key ID: B35D3598 fp: 6429 0D7E F130 C13E C929 6447 73C3 A290 B35D 3598
http://www.openwall.com - bringing security into open computing environments

Crispin Cowan

unread,
Aug 15, 2003, 4:20:56 PM8/15/03
to
Shaun Clowes wrote:

>Perhaps I'm the only one who feels this way, but I believe that the vast
>majority of the exploitation of systems is being performed by people
>with no knowledge of how to write an exploit and that the vast majority
>of exploits are fragile. Doing anything that makes you different from
>every other installation of Linux/HPUX/Solaris/InsertOSHere will
>drastically decrease the changes of any point and click exploit working
>against you.
>
>Could a determined (and knowledgable) attacker still get through? Sure.
>But if we're talking protections that take very little effort to
>implement, have a minor performance impact and will save your
>skin some of the time, it's obvious that it's worth deploying them. As
>long as you're not kidding yourself that you're then totally secure.
>

Exactly: trivial changes will protect you from script kiddies.
Non-bypassability is required to protect you from determined attackers.
It depends on your threat model: how much will a penetration event cost
you? What is it worth to someone to hack you?

>Its kind of reminiscent of that old joke about the two guys running away
>from the lion. You don't have to beat the lion, just the other person.
>

But if you taste better (you are a bank and he is a basement RH box)
then the lion may choose to chase you anyway.

Gerhard Strangar

unread,
Aug 15, 2003, 4:28:05 PM8/15/03
to
--------------ms26B086DDCF7B2FE12CAC155C

Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Theo de Raadt wrote:

> But then a problem shows up. When you use shared libraries, you end
> up with code followed by data followed by code followed by data etc.
> Since you only have one line you can draw in the address space,
> clearly you can't make this work!

Do you know the DOS EXE format? The File contains Code using Offsets in
different Segments. The Loader may move any Segment to any location in
the available memory. To make this possible, the EXE file contains a
relocation table of offsets in the code segment(s) that have to be
modified after loading the segments into memory.
This could be don to shared libraries, too.

> In OpenBSD, we've done steps up to 4.

Okay, this means you have already implemented what I meant.

--
* Origin: (2:2480/8057.2)

--------------ms26B086DDCF7B2FE12CAC155C

MDMwODE0MjIxOTM1WjAjBgkqhkiG9w0BCQQxFgQUT1D1PH7AP1jcUcAq8qw7+IfpOmgwUgYJ
KoZIhvcNAQkPMUUwQzAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgICAIAwBwYFKw4DAgcwDQYI
KoZIhvcNAwICAUAwDQYIKoZIhvcNAwICASgwDQYJKoZIhvcNAQEBBQAEgYC9JA4l66VTM4jY
itnVbRUhToFrX1DxYTvUqf2b9UySoEjx8B5rJanKm3aFXVo+YTzwb2ZK2dCvEMObqhVPVq53
w+yehaVx/5XpwrdLTpxhI/YYadzH+c+zL3AJCvxy2M70xBeCajEJEk39F9aSGruos0daqcOK
440C9rApEhZIYQ==
--------------ms26B086DDCF7B2FE12CAC155C--

Theo de Raadt

unread,
Aug 15, 2003, 5:27:57 PM8/15/03
to
> > W^X is more than just stack protection. It means that all pages that
> > are writeable are also marked as not executable. At least, it means
> > this is how the system by default operates, until some process asks
> > for something that has both write and execute permission.
> >
> > On some architectures W^X is easy, since the native architecture has a
> > execute-permitted bit per page (sparc, sparc64, alpha, hppa, m88k).
> > On other architectures, it is difficult and various hacks have to be
> > done to make it work (i386, powerpc).
>
> It's not difficult at all on x86, but having non-overlapping Segments
> for Code and Data/Stack would limit the virtual address space.

I am not sure if you have heard of this neat technology called "shared
libraries". Either you have never heard of them, or you are unaware
of they work on an x86. Let me be completely blunt. What you are
suggesting is unfeasable. Please go do some learning before making
any more utterly ridiculous proposals.

> This
> doesn't matter if your machine is equipped with 2 GB (RAM+Pagefile) or
> less, because all pages of those 2 GB can completely be mapped to linear
> addresses in either the code or data/stack segment. As soon as there's
> more memory available, you have to decide how large the code and
> data/stack segment should be.

Ridiculous.

> Adressing more than 4 GB on x86 is an ugly hack anyways -PSE as well as
> PAE.

Yet more dribble which is unrelated to the issue at hand.

Anyways, on an i386 you can do W^X somewhat. Not as perfectly as you
can on cpus that have a per-page X bit... Let me try to summarize the
options.

1) Configure the i386 CS code segment limit register so that it cannot
reach into the stack area at the end of memory.

Hence, you can have code below, and your stack above. This only
protects your stack. As many have pointed out, doing so is useless,
unless other protection techologies such as ProPolice are used to
suppliment the protection.

2) Furthermore, try to make the CS code segment limit register reach only
to the end of the data segment.

But then a problem shows up. When you use shared libraries, you end
up with code followed by data followed by code followed by data etc.
Since you only have one line you can draw in the address space,
clearly you can't make this work!

3) To resolve this, we made modifications to ld.so and to the base ELF
binaries and shared library files that are produced. The idea is to
map all CODE from the program, ld.so, and from each of the shared
libraries low in memory, and then to map their respective DATA segments
HIGHER in memory.

We must remember one thing. Each ELF module is internally pre-linked.
This means that the code of a module use relative addressing to access
the data. Or, put another way, the code and data must remain a FIXED
distance from each other in memory; that distance is determined at
link time. You cannot change it at run time without significant
performance problems and other difficulties.

4) So, now that all the code is down below, and all the data is above we
have something like this


stack

gap
gap
gap

libm data
libc data
ld.so data
program data

gap
gap
gap <----

libm code
libc code
ld.so code
0: program code


5) If we are clever, we can now change our kernel to put the CS limit
register at where the arrow is. If new objects are mapped or unmapped
into the address space with X permission, the CS limit register can
change up or down.

No objects above that line can be executed.


In OpenBSD, we've done steps up to 4. We've not done step 5 perfectly
yet (we use a "fixed" line).


Finally, another option:

As an alternative to all this complicated stuff, it is my
understanding that some 32-bit x86 cpus in PAE (64 bit PTEs) mode
honour the highest bit of the PTE as a NX (non-executable) bit. This
would give per-page execution stuff like we have on better cpus.
We've not worked on this yet; it is less valuable since I think it is
only newer Xeons and high-end AMD cpus which support this. And we've
never found documentation for it either :)

Tom 7

unread,
Aug 15, 2003, 5:44:22 PM8/15/03
to

Crispin Cowan <cri...@immunix.com> wrote:

> Array bounds checking offers greater protection than any of these
> protections (StackGuard, ProPolice, PointGuard, W^X, PAX/ASLR, etc.) The
> problem is that the very fastest array bounds protection for C (Bounded
> Pointers) imposes a 5X slowdown on performance, where as these other
> techniques impose overheat somewhere between noise and 20%.

This may be true. Doing "safe" pointers in C is difficult because of
pointer arithmetic. But I think this is a bit unfair to bounds checking in
general--type safe compiled languages like ML achieve array bounds
checking (and other checks) at a much smaller penalty (less than 20% for
array-oriented code in my experience). These languages also provide
protection against other common sources of holes, like integer overflow,
double-frees (most are garbage collected) and printf formatting attacks.
This protection is automatic and absolute; the only thing left to worry
about is bugs in the compiler, system library, and kernel (things that C
programmers already need to worry about, anyway).

In my opinion these languages are utterly practical for Unix network
daemons. Of course, this is a bit more work because you don't just
recompile the program, you have to rewrite it from scratch! But there are
other benefits to maintaining code in a modern, safe, high-level language.

- Tom

[ http://www.cs.cmu.edu/~tom7/ ]

stealth

unread,
Aug 15, 2003, 7:00:22 PM8/15/03
to
On Fri, Aug 15, 2003 at 11:41:18AM +0200, Peter Busser wrote:

Hi,

> The only way to sleep quietly in fact is to feed your computer to a shredder.

Yes, indeed. But if you install PaX and all the other nice and really
usefull things out there I think you can sleep pretty well. I mean
all the bypassing for the really hard stuff (PaX, gr, SELinux)
is really theoretical from what I have seen. I really want to see
that guy (or girl? :) that exploits a GR'ed box remotely where the
target box runs single-service and well audited code. You do not
have to fear that person that gets into it, and you will probably never know
(s)he was there, so who cares?
Not speaking about user-shells, trojans on client-systems and social engenering
here.

> contains millions of lines of code. Auditing this amount of code is simply
> impossible. Furthermore, auditors are humans. Humans make mistakes, not only
> when they are programmers, but also when they are auditors. So audited code
> will still contain security bugs.
>
> In fact, the amount of security in OpenBSD is only slightly less horrible than
> that of most *NIX operating systems (which includes Adamantix for that matter).
>

0 new messages