OpenBSD Gets Even More Secure
Telent writes "As seen in this post by Theo de Raadt, OpenBSD is getting even more secure, working on smashing script kiddies running buffer overflow exploits dead. Tightening PROT_* according to the POSIX standards and creating a non-executable stack on most architectures are just two of the recent enhancements, most of which are in -current now."
I think BSD will always have its place. It is secure for one thing. And nobody wants a GUI on their servers. Running XWindows can create security holes as well.
Consensus is good, but informed dictatorship is better
OpenBSD does not secure by limiting or removing functinality. Instead, it secures through proper programming, working as a team, and tackling issues in sequence.
:)
I understand your joking, but point the next one towards the right area
It's the difference between love of money and love of your job I suppose. People who are more interested in creating a product that THEY want (BSD developers) are more likely to create a product other people will want. People who are creating a product OTHER people want (as in MS developers making products for their managers' current whims) just won't have the heart for it. Of course... an outright disgust and ditrust of your customers helps create a faulty product as well :\
Alito: A vote for Alito is a punch in the eye to put that bitch back in her place!
..but it seems OpenBSD is refusing to die.
A nonexecutable stack is no guarantee of safety. Solaris 2.6 demonstrated this here.
-- Good judgement comes with experience. -- Experience comes with bad judgement.
VMS is probably a close second in terms of security. Its C-2 secure right out of the box. Plus most script kiddies would be left scratching their head trying to use it.
Only the State obtains its revenue by coercion. - Murray Rothbard
Easy! Just change your viewing prefs to not show signatures. That way you won't have to bitch to the world about it EVER again!
Someone in FreeBSD and NetBSD with commit priviledges is surely looking at those patches.
The bigger problem is that the principle of least privilege is not adhered to in world of Unix. Programmers will always write bugs and applications will always have vulnerabilities that can be manipulated. Manipulation of services should only effect the service being manipulated, not the whole system. For example, services should have NO access to anything by default. When you install a service you should set up the specific permissions that it requires (this can be made easy - the app, upon install, can recommend the permissions and you can just say, "okay"). If the app tries to do something that it doesn't normally need to do (like access /home/me/mysecretfile), the system should log an access denied message; the Linux kernel right now can't even audit denied access to files! CHUID permissions to deliver mail to people? A much cleaner mechanism is for the mail server to create the files under its own name and give permission to the user to take ownership of the files.
Linux, and Unix in general, tends to have pretty limited access controls. Even with ACL support, the distros still need to ship with restrictive settings and manage them. A lot can be done to provide a framework under which compromises can be limited and can be audited. Right now we don't have that. Without detection and reaction, how do you know that your prevention is effective?
The "real" Theo de Raadt, with a uid of 646101? I find that a bit hard to believe.
Not really. You can still control the program flow by overwriting the return address, and given the stack-only parameter passing scheme on x86, you can also supply arguments to whatever function you choose to return to (with register arguments, you'd be limited to whatever registers are going to be loaded off the stack before you return, and argument registers are typically not preserved by the callee). While the typical exploit that just wants /bin/sh to run would likely just call system() or execve() or something, if one really wants to run code from the stack, the stack could be set up to return to memcpy() with the arguments pointing at the code to be moved to an executable area, and a subsequent return value that points to the destination. Null bytes would present a problem with (at least) the length argument, assuming the overflow is from a C-style string, but a sufficiently clever attacker could utilize other library functions to patch in the needed null bytes.
Thus, it may make certain attacks marginally harder, but it doesn't stop foreign code from being executable. It's most visible effect would be the problems it causes to legitimate programs that may want to execute dynamically generated code on the stack.
While there is no silver bullet to these sorts of attacks, making the stack grow upward (or strings grow downward) would eliminate a lot more holes than a non-exec stack. Unfortunately, people are too bound by tradition, and still introduce new ABIs that use downward-growing stacks, even when there's no hardware bias against upward-growing stacks, such as on most RISC chips.
Adding SMP will make the kernel more complex, and complexity is bad from a security standpoint.
OpenBSD is supposed to be used for network edge devices - firewalls, etc, in which SMP is not required.
If you want a Unix for your desktop - try Linux, or help out testing FreeBSD 5.0.
Its not about Theo "getting it together" ... no SMP is a design decision that has been made.
smash.
I run: Windows, OS X, Linux, FreeBSD. Just because you have a hammer, doesn't mean everything is a nail.
This is plain stupid. The kernel stack has nothing in common with user stack, so trampolines are a special issue there.
Then, trampolines are not the only way to implement nested functions. Just a neat one.
And finally, gcc has all the hooks to turn the memory protection back on for the little chunk that wants stack execution.
Guess what ? gnu-ada uses trampolines, and it works on OpenBSD current...
Example: A hacker sends a packet that exploits a buffer overflow bug to insert some malicious code into memory. The computer won't execute it because it's writeable, and it doesn't execute writeable pages. But that's okay! The worm cleverly inserted the data into a location it knew was writeable, but would eventually become readable. Sure enough, later on another function makes that location executable and then executes it.
The thing is that stuff written to memory by usual
apps are written into PROT_WRITE areas. These in
turn usually never gets mprotect()ed to another
status by the apps. A common exploit would normally
send malicious data to the app making the app copy
that data into an area that had both PROT_WRITE
and PROT_EXEC. Then, it would make the app jump into
this area.
So, you can always use bugs to have the code jump
from one place to another, but if the app doesn't
have any mprotect() code (mine never does =) then
it would be pretty hard for the exploiter to rewrite
the rules of his particurlar page using code that isn't
his own at all to make it possible for him to jump
into his own code.
Until you have found a way to execute your own code,
finding a call to mprotect() with *EXACTLY* the correct
args to make page 0x056df800 go from PROT_WRITE to
PROT_EXEC will be hard++.
So you end up with a chicken-egg-problem. The
malicious code could of course make its own page
PROT_EXEC. if it could execute mprotect(), and since it can't
execute anything without PROT_EXEC, it cannot run mprotect() at all.
-- I'm as unique as everyone else.
Also, you don't need an executable heap/stack for these overflows to cause damage (overwrite access tokens, change flag states, etc.)
Sure every little bit helps, but it's still kind of a losing battle.
IMO, it would be better to spend more time educating people and making it socially unacceptable to use C/C++ when they could just as easily use a high level language with bounds checking. You know, like LISP people have been saying for 30 years.. ;)
But alas this is a touchy subject.
It would help if they stopped IRCing from their CVS repository machines. That may not make their code more secure, but it will help keep the back doors and trojans out.
I am constantly amazed that people who commit this kind of beginner's mistake have the gall to call their software "secure". And then they ship sendmail and BIND with it. ROTFL
I was thinking about this on my drive into work this morning, and I came to the conclusion that what we need to do is to change the C style stack usage to use two or three stacks.
Consider: C uses the stack for three types of information: call/return information, parameter passing, and local variable storage. I assert that this is the cause of most of the stack problems in C - you are using the same thing for three different needs.
Let me discuss each of the three uses in turn. I will use x86 terminology for this discussion because that is the primary architecture used for Linux and because that is what I am most familiar with, but you should be able to generalize my points without much problem.
First, you have the call/return stack. This needs to the be CPU stack so that normal CALL/RET operations work. The only things that should be stored here are the actual return addresses, as well as possibly register saves (esp. for interrupt routines). However, in a unified stack design it is possible for the bad guys to modify the return address. Thus, even in a non-executable stack environment I can still change the return address to point to a function, say exec().
Second, you have the parameter passing stack. Ideally the only thing on this stack would be parameters passed down to the function from the caller. However, in a unified stack design, I can modify this stack to contain data - thus I can create a pointer to the string "/bin/bash" on the stack. With this and with the call/return modification above, I can cause the current function to "return" to exec(), with "/bin/bash" as the arg. Boom. Remote shell.
Third, you have local variable storage. If this space were seperate from the other two stacks, then overflowing a local buffer, while still bad, would not be able to modify the return address nor would it be able to create parameters. Ideally, every subroutine would be given its own sparely mapped local space - thus boundary errors would likely throw a page fault (granted, the cost of setting such a mapping up for each subroutine call would be prohibitive, so it is unlikely to happen without some form of hardware acceleration. Perhaps a low/high limit register could be added to the various index functions, such that an access relative to EBP, ESI, EDI would fault if it went out of range.)
However, consider just seperating the stack into three areas, widely seperated. ESP would point to the hardware stack. EBP to the local storage area, and ESI to the parameter block (with EDI pointing to "this" for C++). Now, a bad programmer has a buffer in local storage and doesn't range check it. A would-be exploiter still cannot modify the return address nor can he modify the parameter stack. The most he could do would be to hose the local variable storage (granted, that might still allow him to corrupt the local vars for some other function and perhaps get an exploit that way, but it would be even more difficult).
Granted, to do what I just suggested means throwing out *all* standard libraries, tools, compilers, and so forth - I am not actually suggesting that the x86 family do this! However, for new architectures like Sledgehammer et. al, this might be the time to make such a break.
www.eFax.com are spammers
SMP simply is not a requirement for OpenBSD's niche. Besides, if you want SMP in OpenBSD, there's nothing to stop you forking it and building your own...
smash.
I run: Windows, OS X, Linux, FreeBSD. Just because you have a hammer, doesn't mean everything is a nail.