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.
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
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 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