Posted by
CmdrTaco
on from the stuff-to-think-about dept.
pomac writes "Check out Libsafe for a great effort in protecting outdated systems against stack attacks or buffer overflows. I would love to see some constructive opinions on this. " You and me both.
This is obsolete for Open Source.
by
zCyl
·
· Score: 3
We've had a tool that protects open source programs from calling known bad calls for some time now. It's called grep. Grep your code for bad calls, find them, fix them, then don't waste 4 metric tons of overhead running all your software with a wrapper.
The ideal solution would be to make a tiny little perl script that pattern matched code for all these known bad calls, and then printed out the file, line number, and reason why the call is known to be bad.
Re:This is obsolete for Open Source.
by
technos
·
· Score: 3
Okay.. Let's put it this way. I have a mission critical program. We'll call it Midnight Modeller. Now, this program is the only one with the particular feature set I need. Unfortunatly, its been so long unmaintained that all I can get functioning is a binary that is known vunerable.
I have two options; Install the wrappers, or slog through 18,000 lines of code to modernize it.
Or another:
I have a commercial application. Let's call it Microsoft Office 2001 for Linux. Am I to trust that in that huge, behemoth of Microsoftian bloat there isn't some exploitable code?
I have two options; Install the wrappers, or pay the vendor BIG MONEY for a copy of the source and audit it.
-- .sig: Now legally binding!
Re:This is obsolete for Open Source.
by
Cramer
·
· Score: 3
Actually, it's much simpler than that... Linux has had, in one form or another, a "non-executable stack" patch for some time now. There has been heated debates on it's usefulness, however. Most buffer overflow tricks overwrite the return address on the stack as well as stick there own instructions there. If the stack is not executable then it's a hell of alot harder to get the program to do what you want it to -- unless "crash" is what you want it to do. It would be very difficult to implant your own instructions; and very few programs have something like 'system("/bin/sh");' in them.
Such patches also cause a problem for programs that legitimately alter their code -- self-modifying code. Granted, there are very few such programs and there are ways to make them work. (The Distributed.Net client has a self-modifying core.)
Re:This is obsolete for Open Source.
by
rlk
·
· Score: 3
Grep's great for finding calls to gets that are basically unsafe under virtually any conditions. It can find calls to other dangerous functions (strcat, strcpy, sprintf for example) if you have the source handy, but it doesn't help you decide whether each call is dangerous or not. For example, strcpy is dangerous, but if the length of the string being copied is provably bounded, it may be quite safe.
I consider gets to be essentially unsafe in all circumstances because it relies upon good external behavior. I suppose one can always come up with a safe example -- a program pipes, forks, and the child rebinds stdin to the pipe -- but that's contrived. It would be nice to replace the substitute function for gets with one that aborts if gets (and probably also scanf) is ever called.
The real advantage of libsafe is that it catches problems that happen at runtime with calls that might otherwise be reasonable. It's a backstop. The fact that stack smashes still happen is clear evidence that grepping source isn't sufficient.
The concept seems useful, but hokey.
It only checks for a few standard bugs, and
even then, the checking isn't airtight.
It won't catch non-library overflows.
It may encourage people to think unsafe programs
are safe. Incidentally, if you're not familiar with how buffer overflow bugs are found and exploited, the classic
The Tao of Windows Buffer Overflow from
Cult of the Dead Cow is a good tutorial.
I'm amazed that people are still using the old
unchecked C library functions. There are checked versions for all of them. I stopped using the
unchecked versions in the early 1980s.
As was suggested in 1995, it's time to pull all those functions out of the standard library and move them to something called "deprecated". The open-source community should try this; it would break lots of programs at compile time, but they'd be easy to fix.
And you've got the source.
I downloaded the code and looked through their whitepaper and the source code a bit. Here's the basic technique:
Install the libsafe library in/lib/libsafe.so.1.3. (Red Hat Linux 6.2 users might want to get the RPM.)
Set the environment variable LD_PRELOAD to point to the libsafe library. (The RPM installs shell init scripts into/etc/profile.d for Red Hat 6.2 shells to do this.)
Calls to "unsafe" C library routines (e.g. strcpy(3)) will be trapped by libsafe, which will figure out the size of the stack frame and reimplement the "unsafe" function safely (e.g. with memcpy(3)).
If the program attempts to overflow the stack frame (presumably from a stack-smashing attack), a message is logged with syslog (into/var/log/secure) and the process group is killed with the SIGKILL signal.
This interception is done at runtime, and works without source code or recompiling
This technique can guard against stack-smashing exploits that haven't even been discovered yet. (And might even help discover them earlier!)
There are a few caveats here:
There is a performance impact, but the overhead appears to be relatively low.
Since this technique relies on the dynamic linker (ld.so) to intercept the unsafe calls, statically-linked programs cannot be protected with this technique.
If LD_PRELOAD is used, setuid programs will not be protected because ld.so (properly) doesn't trust the environment variables when running setuid, and thus ignores LD_PRELOAD.
For system-wide protection, it is safer to use/etc/ld.so.preload instead of LD_PRELOAD; it will apply to all (dynamically-linked) programs, including setuid programs, and cannot be accidently lost from the environment.
To the packager of the RPM: how about using/etc/ld.so.preload instead of LD_PRELOAD? Maybe in libsafe-1.3-3.*.rpm?
--
Deven
"Simple things should be simple, and complex things should be possible."- Alan Kay
Libsafe and StackGuard
by
Crispin+Cowan
·
· Score: 4
Perry Wagle (principle StackGuard developer) has done some analysis comparing libsafe to stackguard. Here's the short version:
Use StackGuard when you can, because it's safer:
Libsafe only protects selected library string functions, while StackGuard protects all potential sources of stack overflow.
Libsafe depends on the existance of the frame pointer in the stack frame to parse/detect the stack frame. Unfortunately, the frame pointer may not be there, either because of a compile option to remove it, or because the optimizer took it out.
Use libsafe where you cannot use StackGuard. It's better than nothing, and it can protect closed-source apps where StackGuard cannot.
My further comment on libsafe: the paper that the authors will be
presenting at USENIX in June presents two forms of defense ("library
intercept" and binary-rewrite (BRW)) and only the library intercept
appears to be embodied in the publicly available libsafe, which is why
libsafe only protects against overflows that use particular string
library functions.
The BRW method is a pseudo-compiler that can transform binaries into "safe" programs by transforming the binary. It copies program onto the heap, inserting checks as it goes. The copy-to-the-heap is to make space for the additional checks. I really like the BRW method, and hope it becomes available.
If my understanding is mistaken, and BRW is actually in the distributed libsafe, please correct me.
Non-executable stacks are no solution.
by
Deven
·
· Score: 4
Making the stack non-executable can intefere with valid code (e.g. signal handlers, nested function calls and trampoline functions) while leaving other stack-smashing exploits open to exploit. The libsafe library comes with an example exploit that will give you a shell despite a non-executable stack. Using libsafe will protect you from this attack without harming valid code. Making the stack non-executable remains vulnerable to this attack while breaking otherwise-valid code; the Linux kernel folks were right to reject the non-executable-stack "fix" to the problem.
--
Deven
"Simple things should be simple, and complex things should be possible."- Alan Kay
We've had a tool that protects open source programs from calling known bad calls for some time now. It's called grep. Grep your code for bad calls, find them, fix them, then don't waste 4 metric tons of overhead running all your software with a wrapper.
The ideal solution would be to make a tiny little perl script that pattern matched code for all these known bad calls, and then printed out the file, line number, and reason why the call is known to be bad.
Well, the docs say the impact is negligible, so I decided to give it a shot.
Box is a celery, 450mhz, 128MB RAM, intel i810 chipset, kernel is 2.2.12-20 (stock RH 6.1)
Apache is 1.3.12, freshly compiled just for this benchmark.
Without:
Running 15,000 requests over three iterations:
1: 373 req/sec - 677 kb/sec
2: 374 req/sec - 675 kb/sec
3: 375 req/sec - 679 kb/sec
With libsafe:
1: 334 req/sec - 605 kb/sec
2: 343 req/sec - 621 kb/sec
3: 355 req/sec - 642 kb/sec
Benchmark command line was:
./ab -n5000 -c100 -k http://cobalt/index.html
So, not bad, it it does what it says it does. The box was loaded to the gills, so every little extra makes a difference.
I'll probly be putting this to at least some serious testing in our production environment.
--
blue
i browse at -1 because they're funnier than you are.
I'm amazed that people are still using the old unchecked C library functions. There are checked versions for all of them. I stopped using the unchecked versions in the early 1980s. As was suggested in 1995, it's time to pull all those functions out of the standard library and move them to something called "deprecated". The open-source community should try this; it would break lots of programs at compile time, but they'd be easy to fix. And you've got the source.
I downloaded the code and looked through their whitepaper and the source code a bit. Here's the basic technique:
- Install the libsafe library in
/lib/libsafe.so.1.3. (Red Hat Linux 6.2 users might want to get the RPM .) - Set the environment variable LD_PRELOAD to point to the libsafe library. (The RPM installs shell init scripts into
/etc/profile.d for Red Hat 6.2 shells to do this.) - Calls to "unsafe" C library routines (e.g. strcpy(3)) will be trapped by libsafe, which will figure out the size of the stack frame and reimplement the "unsafe" function safely (e.g. with memcpy(3)).
- If the program attempts to overflow the stack frame (presumably from a stack-smashing attack), a message is logged with syslog (into
/var/log/secure) and the process group is killed with the SIGKILL signal. - This interception is done at runtime, and works without source code or recompiling
- This technique can guard against stack-smashing exploits that haven't even been discovered yet. (And might even help discover them earlier!)
There are a few caveats here:- There is a performance impact, but the overhead appears to be relatively low.
- Since this technique relies on the dynamic linker (ld.so) to intercept the unsafe calls, statically-linked programs cannot be protected with this technique.
- If LD_PRELOAD is used, setuid programs will not be protected because ld.so (properly) doesn't trust the environment variables when running setuid, and thus ignores LD_PRELOAD.
- For system-wide protection, it is safer to use
/etc/ld.so.preload instead of LD_PRELOAD; it will apply to all (dynamically-linked) programs, including setuid programs, and cannot be accidently lost from the environment.
To the packager of the RPM: how about usingDeven
"Simple things should be simple, and complex things should be possible." - Alan Kay
- Use StackGuard when you can, because it's safer:
- Libsafe only protects selected library string functions, while StackGuard protects all potential sources of stack overflow.
- Libsafe depends on the existance of the frame pointer in the stack frame to parse/detect the stack frame. Unfortunately, the frame pointer may not be there, either because of a compile option to remove it, or because the optimizer took it out.
- Use libsafe where you cannot use StackGuard. It's better than nothing, and it can protect closed-source apps where StackGuard cannot.
The long version of the analysis is here.My further comment on libsafe: the paper that the authors will be presenting at USENIX in June presents two forms of defense ("library intercept" and binary-rewrite (BRW)) and only the library intercept appears to be embodied in the publicly available libsafe, which is why libsafe only protects against overflows that use particular string library functions.
The BRW method is a pseudo-compiler that can transform binaries into "safe" programs by transforming the binary. It copies program onto the heap, inserting checks as it goes. The copy-to-the-heap is to make space for the additional checks. I really like the BRW method, and hope it becomes available.
If my understanding is mistaken, and BRW is actually in the distributed libsafe, please correct me.
Crispin
-------
CTO, WireX Communciations, Inc.
Immunix: Free Hardened Linux
Making the stack non-executable can intefere with valid code (e.g. signal handlers, nested function calls and trampoline functions) while leaving other stack-smashing exploits open to exploit. The libsafe library comes with an example exploit that will give you a shell despite a non-executable stack. Using libsafe will protect you from this attack without harming valid code. Making the stack non-executable remains vulnerable to this attack while breaking otherwise-valid code; the Linux kernel folks were right to reject the non-executable-stack "fix" to the problem.
Deven
"Simple things should be simple, and complex things should be possible." - Alan Kay