Zlib Security Flaw Could Cause Widespread Trouble
BlueSharpieOfDoom writes "Whitedust has an interesting article posted about the new zlib buffer overflow. It affects countless software applications, even on Microsoft Windows. Some of the most affected application are those that are able to use the PNG graphic format, as zlib is wildely used in compression of PNG images. Zlib was also in the news in 2002 because of a flaw found in the way it handled memory allocation. The new hole could allow remote attackers to crash the vulnerable program or even the possiblity of executing arbitrary code."
Both Debian and Ubuntu released the patch for this problem 2 days ago. I assume the other big names in the Linux world have or will follow suit shortly.
/Mikael
Greylisting is to SMTP as NAT is to IPv4
Also hardware support would help. Even 25 years ago the ICL 2900 series systems had a native hardware 'pointer' type (they called it a descriptor). This included in it the size of the object pointed to, and the hardware would check that any dereferences were not out of bounds.
http://forums.gentoo.org/viewtopic-t-356659.html
I'm running RHN alert notification on Fedora Core 3, and my version of zlib has already been updated with a patch for CAN-2005-2096, the zlib overflow bug.
It's interesting to read about these as they occur, but it's a nice feeling that my operating system is so well taken care of. Too bad that all personal computers aren't set up for this kind of timely response. I wonder about those millions of library computers, home PCs, small business computers, and other institutional setups where no one even understands the concept of an update, let alone regularly runs the Windows "security" update program.
Another reason to use Linux!
it's = "it is"; its = possessive. E.g., it's flapping its wings.
There also exist modifications to gcc that perform the same function. A little checking on your part was all that was necessary to not fall into the publicization trap.
However, all such methods introduce a very noticable performance penalty.
Furthermore, there are documented ways of bypassing all such stack protection mechanisms.
Stop bitching. Audit your goddamn code already. Or would you rather all the bugs be found by the bad guys (this one was found by the Gentoo security team)?
..there has been no security audit that found this flaw.
Been at the crack pipe again? "Provided and/or discovered by: Tavis Ormandy, Gentoo Linux Security Audit Team" here.
It is really something that this flaw impacts so many applications.
This situation is unnecessary; the problem is that C is not a type-safe language, like ML, CAML, Haskell, Common Lisp, Scheme, Java, etc.
You could write that code in SML/CAML/Common Lisp and likely get it to run as fast or faster than the original (particularly if you did some space/time tradeoffs ala partial evaluation). Integration with the applications in the form of a library would be the tough part.
Here's a provocative bit from Paul Graham (Lisp expert entrepreneur) on buffer overflows.
http://www.thebricktestament.com/the_law/when_to_
Automatic buffer overflow protection only covers the straightforward buffer overflow problems, i.e. array index overflows. In the case of more complex pointer arithmetic, where most of these problems occur, automatic protection is not possible (at least not without losing the option of pointer arithmetic).
Actually, automatic checking is very much possible, and has been for years. For example, Bounds checking gcc (that website is down right now, so try my page on the subject). That was written in 1994, and there are newer systems available now which don't have such a serious performance penalty.
The real solution is to stop writing critical code in C. Other languages provide bounds checking, and are faster and safer than C: for example OCaml which I prefer nowadays.
Rich.
libguestfs - tools for accessing and modifying virtual machine disk images
Actually, x86 already does, but nobody uses these features. When they fixed segmentation with the 386, segments were now accessed through selectors and offsets. The selectors pointed to one of two tables (GDT - global descriptor table or LDT - local descriptor table). Whenever a memory access was made using a selector, the CPU would look up the descriptor corresponding to the selector. It would check whether the current program had necessary access rights and privilege. If not, then a GPF would be thrown. Segments can be marked as read-only, read-write, executable and maybe a few more combos. Although the GDT and LDT each have only room for 8192 entries, that's still probably more than most programs would need. Each segment could correspond to a single object or array of primitive objects. There would be no buffer overflows because the CPU catches attempts to go beyond the limit of a segment. Stack data couldn't be executed inadvertently because the stack segment would properly be marked as non-executable.
There are a few reasons, though, why we don't use this system. One is that loading descriptors is slow because it was never optimized in the CPU with the equivalent of a TLB as for paging. The other is that using segmentation requires 48-bit pointers rather than 32-bit pointers, or it requires loading segmentation registers and doing a dance with those. I suppose using longer pointers was a problem back in the days when memory was scarce, but it's hardly a problem now (check out 64-bit). Intel *could have* made segment descriptor access checks and loading fast, but I guess there wasn't a demand for it once paging was available.
For the undead crowd out there:
OpenBSD is affected, and was patched on the 6th of June
FreeBSD is affected, and was patched on the 6th of June
NetBSD base system is not affected, but a zlib from pkgsrc is, and was patched on the 8th of June
...instead of looking for information on the NX bit from the buffer overflow page in Wikipedia, look up the thing specifically here. Yeah.
Happy people make bad consumers.
In fact, this flaw was found by a security audit of an open source project, not by any of the closed source projects (like Microsoft Office) that make use of it.
This is really an argument for versioning dynamic libraries very carefully. The Linux dynamic linker has perfectly good support for avoiding problems like this. Each shared library has a "SONAME" field. Programs linked against the library should be able to use any later version of the library with the same SONAME. If the library changes in some way that breaks desireable behavior, it is supposed to get a new SONAME. The system keeps two sets of symlinks, in addition to the object files: libfoo.so is the latest version and libfoo.so.{version} is the latest version of a compatible series. When you link a program, you use the libfoo.so to find which series is newest. When you run a program, you use libfoo.so.{version}, so you get the newest compatible version.
It sounds like the problem you had was that the common library version number wasn't changed when it should have been. If it had been changed, there would have been no effect on any of the existing programs, static or dynamic. Of course, for a two-line fix to a function which only changes the behavior of the library when dealing with corrupted files, and resulted in a buffer overflow instead of an error, the change won't break anything except attacks, so keeping the same SONAME is right.
Note that you can see this by doing "ldd {program}", which will report how it looks for each library and what it finds. And you can see that zlib claims to be backwards compatible all the way through 1.x, while openssl is only to 0.9.7.
> Nothing more fun than firing off a couple apt-get upgrades in the morning while watching your bsd/gentoo friends sit around rebuilding
What!!! The gentoo/bsd crowd wouldn't staticly link zlib. They would only need to rebuild one package. You sir, are full of crap.
Oh please. When are we going to get past, "I know! Let's just write perfect software all the time!"
There will always be some subset of people who refuse to accept the impossibility of absolute perfection. I believe their thinking goes like this:
(I never had to work for anyone who said the above, but my brother in law, a coder for a large trucking company, had to put up with a "quality consultant" whose entire theory was essentially the above, punctuated with shouts of "attention to detail, people!" in between such lectures. A similar consultant is documented in an email in "The Dilbert Principle". Sadly, it's probably not the same guy.)
If a job's not worth doing, it's not worth doing right.
Luckily there were some Gentooists recompiling their systems packages every so often, since the vulnerability was found by the Gentoo Linux Security Audit Team here. I've always thought the the more projects making use of the same library, as well as, the platforms a project is ported to eventually improves the quality and stability of the code. In this case the security was improved, but in general the abstracted parts of the code improve.
--Excyl
What are you talking about? All I had to do was to rebuild zlib and restart apps that used zlib. Oh, I did that while I ssh back home from work, all I had to do was to fire off a couple commands to do the same fix as apt-get.
Please, learn how a Linux/BSD system work, how linked/static binaries work before start critiquing other distributions with non-sense.
Please direct all bug reports to
Python can't, at least without embedding the python interpreter in the dll.
What's more, you say that C can work with (at least as a library) every other language out there. So what's the problem with a small C-language interface that just calls the Python function and returns the result?
Any language supports calling C libraries from that language. You have to, because for many things the only library available is in C, and there are millions of C libraries. Not so many support calling that language libraries from C - why would they? A big part of their attractiveness is their extensive standard library.
I am trolling
Personally, I work down a suite of tools to help ensure reliability:
1. Use a language and run-time that enforces bounds checking and managed memory. This is not always practial because of performance issues.
2. If I can't do that, use libraries that hide the complexity of managing memory (smart pointers, smart arrays, and the like). This is not entirely reliable because it depends on the discipline of the programmer.
3. If I can't do that, I use tools like valgrind in conjunctgion with unit testing, so that l can find memory errors after the fact. This can't be completely trusted because it depends on the completeness of the test suite.
4. Code carefully and cross my fingers.