Alexey Toptygin wrote:
On Fri, 18 Aug 2006, Don wrote:
But, I understand your point. Why can't you
put the stack in
a separate "segment" (intel-speak) and give that segment *only*
read/write attributes (i.e. no execute). This stops hackers
from executing code on the stack. Same could apply to purely
*data* "segments".
This is commonly done, and called W^X (write xor execute). See:
http://en.wikipedia.org/wiki/W%5EX
Yes, I've already implemented this. And, done everything
that (I *hope*!) protects the *system* from malicious code
(even in "add on" modules). But, now I am trying to
consider how malicious code can tinker with userland
objects. :-( A user doesn't really *care* that your
OS was "protected" if he still ends up losing *his* data!
:-/
But, it
doesn't prevent someone diddling (that's a technical
term; it means "screwing with" :> ) the contents of the stack
and thereby effecting a return to some portion of the *text*
space that does their bidding for them. Perhaps returning
to the middle of a multibyte/word instruction sequence that
*coincidentally* does something they want?
Of course, they have access to *your* binaries (if you
are running an O-t-S OS) so they can hunt around for whatever
byte sequence they happen to want.
Still, seems like a longshot. I'd imagine most exploits could
be prevented just by removing the execute ability from segments
that are known NOT to contain code.
Many can be, which is why OpenBSD among others implements it. This is
how they were able to make the "no remote root vulnerabilities in X
years" claim. However, securlty experts have been able to exploit many
stack bugs despite this protection, usually with "return to libc"
But, even so, they can't get into the "kernel's" protection
domain through those mechanisms -- unless the kernel wasnt
well protected (?)
attacks. There are many papers out there on how to
exploit a W^X
protected process, and many others on additional protections that defeat
these attacks. Mostly these protections rely on randomizing the address
space of a running process or changing the calling convention so stack
integrity is verified somehow before each return.
But, user applications can be developed using tools that
fail to observe your conventions WITHIN their application.
I.e. it seems like the only mechanisms that you can put
in place are those that are invoked at protection boundaries.
(?)
[I'm
intensely interested in this as to how it can be done
to make applications in consumer devices "hacker hardened"]
There is a ton of work in this area, W^X is just the simplest and most
efficient (and maybe oldest) method. Some people have gone so far as to
statistically profile the pattern of system calls an application makes,
and to kill it if the pattern suddenly changes (this is the least
practical approach I've heard of :-).
Thanks, I will see if I can come up with some suitable search
terms...