Live data from Hacker News

Glibc getaddrinfo stack-based buffer overflow

googleonlinesecurity.blogspot.com

461–470 of 480 posts

Re: Glibc getaddrinfo stack-based buffer overflow

#461
post #386
post #267

Earlier quoted context omitted.

Of course, but then you've hamstrung the typesystem that makes Rust safer than C, and generated a lot of work for developers who have to convert all internal types to #[repr(C)] ones at library boundaries. Rust without cross-crate generics is way less fun--you lose "theorems for free", unless you can make guarantees about the pre-ABI translation to/from C types (which would ultimately amount to defining an ABI).

You've hamstring the type system at the interface , internally you still get all the benefits. In any case, a typical use-case for a shared library like this is embedded into other applications, which may not be written in Rust at all, and hence things like generics don't work anyway. In fact, this is reflected in a common way to expose an interface in this manner: have a main Rust interface (i.e. with normal generic…

Personally, I've always thought that type safety provides the most benefit at boundaries between codebases: you have people composing pieces that they don't understand, and the types serve to guide how those pieces can be composed to result in a correct program. Within a library, it's not uncommon that the core data structure or processing is only correct because a human looked hard at it--I would be surprised if Rust implementations of, say, font rendering, used types internally to guarantee the correctness of their rendering relative to a formal specification. Instead they're using types to make sure they process all input, or make sure they handle memory safely.

Generics are another place where this becomes the case: if a library exposes a "fold" function generic over both the accumulator and element type, accepting void* instead of T and U means you lose the ability to make sure user don't mix up places where you want an element and places where you want an accumulator.

Dynamically upgradable cross-crate generics, ultimately, require recompilation if you want the performance benefits of monomorphization. But it would be possible to have patchable sites around inlined generics that the dynamic linker could change to instead jump to a version which did not inline generics and which simply called into a non-type-specialized routine in the other library. You'd end up with two versions of compiled code in the binary around each call site for a generic: an inlined-optimized-and-code-motioned one, as usual, and an assumption-free one compiled considering generics to be opaque blobs and using dynamic dispatch for trait methods so that the same code can be used for all instantiations of the generic function.

For example, a function parameterized over an unconstrained type T can't do anything useful with values of that type, except dropping them. Thus code would be generated in which the call to the drop impl would be dynamic.

I think this can be made to work w/r/t non-object-safe trait bounds as well, but I'm not sure how to justify that.

I think library changes which alter which impls get called on which types (i.e. which affect specialization) would still be ABI-breaking, unless you had some more cleverness (type-id-based dispatch for the deoptimized case? ugh) to deal with that complexity.

I also don't think this solution is ideal, but I think it's very important for Rust to be considering these issues, because given the design of the current modern operating system, having separately upgradable libraries is really important. Maybe Rust should be pushing for changes in the OS design, in a direction like NixOS is taking, but it seems like it isn't ready use for building the future's userspace when it can't provide both safety benefit across library boundaries and separate upgradeability.

Re: Glibc getaddrinfo stack-based buffer overflow

#462
post #423

Earlier quoted context omitted.

The past four years of modern development practices have run screaming from the concept. Learning why the systems used to work they way they did was, like, super hard, so they reinvented the wheel and are running into the same problems that caused us to make shared libraries/COW/etc in the first place.

You've pretty fundamentally misunderstood them if you think immutable practices in anyway damage the ability to deploy fixes. Years of shared library hell is what causes things like this to go unfixed.

Immutability in software development & deployment is, for the vast majority of use cases, completely unnecessary. The only reason people talk about it now is everyone has a fetish over using simple software rather than designing software that works well.

And 'immutable practices' don't damage anything - they simply make things take longer, duplicate effort, make inefficient use of resources, and make everything generally more inflexible. The only benefit seems to be high level abstraction at the cost of everything else.

Re: Glibc getaddrinfo stack-based buffer overflow

#463
post #367

Earlier quoted context omitted.

> It was literally weeks after Heartbleed. The screams for modern languages with managed runtimes had barely subsided. Then Tomcat, in common use world wide in the poster boy managed language, had a bug with exactly the same impact. You're talking about POODLE? Not remotely the same impact. It was a severe vulnerability, but it only leaked plaintext, not key material. > I like modern languages as much as the next guy…

> You're talking about POODLE? Why would I? That wasn't Tomcat, and it didn't leak keys. I won't read through the CVE list right now (because it is long , and that's only counting Tomcat and not the JRE itself), but it reused buffers and leaked potentially anything, very much like Heartbleed. If you were in a Java shop at the time you know about it. > It's not about adding abstraction. There are plenty of safe system…

> If you were in a Java shop at the time you know about it.

False; I was in a Java shop at the time and I don't know about it (though we ran things on Jetty (and later Netty) rather than Tomcat because we felt the code quality was higher).

Re: Glibc getaddrinfo stack-based buffer overflow

#464
post #160

> "The glibc DNS client side resolver is vulnerable to a stack-based buffer overflow when the getaddrinfo() library function is used. Software using this function may be exploited with attacker-controlled domain names, attacker-controlled DNS servers, or through a man-in-the-middle attack." > "The vectors to trigger this buffer overflow are very common and can include ssh, sudo, and curl. We are confident that the ex…

Is djbdns vulnerable? It does not use these routines. I've never needed ENDS0, but maybe the need will arise someday. Meanwhile... Short term, I'd prefer to expunge all "C networking code" originating from BIND authors, e.g., libresolv.

The fact that djbdns doesn't use BIND code is not really relevant. The problem at hand is in the BIND DNS client library that is compiled and linked into applications. It's triggered by sending responses larger than 2048 bytes to those applications. The only way that djbdns factors into it is whether an attacker, running a content DNS server out on Internet, can manage to get such a DNS response through a DNS proxy server such as dnscache, to that BIND DNS client library code running in the application.

Now one might think that the discussion at https://news.ycombinator.com/item?id=11110646 already covers this. All that the content DNS server has to do is set the TC flag in the DNS/UDP response, and it can quite happily get the proxy DNS server to re-try via DNS/TCP. The interesting point is that in fact that discussion does not cover this.

This is because the idea that one can exploit this with a malicious content DNS server has as its unstated premise that DNS/UDP and DNS/TCP responses are passed straight through caching DNS proxies. This is the case for some DNS proxy softwares, where if the data have just come in from the back end and form a complete answer, they are passed through as the front-end answer. It isn't the case for dnscache. dnscache always answers from cache, even if the data have just arrived from a back-end transaction.

So those "crafted DNS responses" beginning with 2048 bytes of valid protocol, that the malicious content DNS server has to generate, have to survive being unpacked, stuffed into dnscache's cache, extracted back out of dnscache's cache, and turned into an answer response by dnscache's from-scratch answer construction code. And this without being able to use the authority or additional sections, without being able to use more than one (non-CNAME) RRset in the answer section, and without any guarantee of any given RRset ordering. This is ... somewhat difficult.

The devil in the details of this problem lies in one sentence of the analysis that accompanies the patch:

> Overflowing bytes are entirely under the control of the attacker and are the result of a crafted DNS response.

If you've done as the people at https://news.ycombinator.com/item?id=11112527 and https://www.reddit.com/r/netsec/comments/462xx0/glibc_getadd... did, you might have convinced yourself how simple it is to exploit this. Just set up a malicious content DNS server that does what this does, and Bob's Your Uncle. But in fact those demonstrations are not how DNS lookups work. People do not point the BIND DNS client library at (malicious) content DNS servers. The DNS client library is pointed at the front end of a proxy DNS server, which performs back-end lookups to the (malicious) content DNS servers.

* http://homepage.ntlworld.com./jonathan.deboynepollard/FGA/dn...

So one has to take into account what the proxy DNS server does in between its back end and its front end. The response returned to the BIND DNS client library from the front end is not "entirely under the control of the attacker". As in the case of dnscache, where front end responses are constructed from cache and from scratch, it's actually quite difficult for the attacker to control it at all, let alone cause dnscache to send a valid-flawed-valid response sequence. It's not just dnscache where this is a difficulty for an attacker, either.

Which is why the analysis talks of man-in-the-middle attacks. To exploit this with far greater chance of success, one gets in between the BIND DNS client library and the proxy DNS server, or just plain supplants/subverts the proxy DNS server. Which is yet another reason why it's a good idea to run a proxy DNS server locally, on each machine or at least on the LAN, and make sure that "local" traffic is blocked at relevant machine/LAN borders. An attacker who can field DNS traffic to [::1]:53 or 127.0.0.1:53 in order to be that man in the middle has already had to overcome some quite tricky obstacles. (-:

* http://homepage.ntlworld.com./jonathan.deboynepollard/FGA/dn...

It's worth noting that we've been here before. A lot.

* https://cr.yp.to/djbdns/res-disaster.html

* http://www.kb.cert.org/vuls/id/542971

* http://www.kb.cert.org/vuls/id/803539

* http://www.kb.cert.org/vuls/id/844360

... And so on.

Re: Glibc getaddrinfo stack-based buffer overflow

#465
post #440
post #325

If I point the local DNS resolver to Google's DNS server as a temp fix (8.8.8.8) in /etc/resolv.conf , will that mitigate the threat before the patch?

The problem is DNS/UDP and DNS/TCP responses that are larger than 2048 bytes hitting your BIND DNS client library. Do you have any reason to believe that Google Public DNS (in your part of the world) always limits its responses to smaller than 2048 bytes?

Google's DNS relay may take steps to sanitize malicious DNS responses.

Re: Glibc getaddrinfo stack-based buffer overflow

#466
I think new generation wants to take over linux with their new ideas but in reality they just want to prove themselves and prepared to completely ruin it in the process.. well. Cos they just young and want new things. They know big words and think they now the world and they hate their parents... so in short - they want to do to the Linux what the previous generation did to windows... karma.

P.s. whatever language you use its irrelevant. Bugs are in the heads. Code is just the reflection.

Re: Glibc getaddrinfo stack-based buffer overflow

#467
post #378
post #86

Earlier quoted context omitted.

You sure can prove that any correct code does something correct, but you can never prove something about a program outside of a machine-checked formal proof.

The problem is that it's far more difficult to prove what code doesn't do than what it does. I can write a function to do X, Y and Z, and I can show, through observation and aggressive testing, that it does indeed do X,Y and Z....but its a lot harder to prove that it only does X,Y and Z and nothing else. Memory safety is just one expression of this problem.

In the typical framework (refinement), if you prove your function does X, Y, and Z, then it does exactly X, Y, and Z. Please don't take my comment out of the context of formal, machine-checked proofs. It is hard, and that's my point.

Re: Glibc getaddrinfo stack-based buffer overflow

#468
post #454

Earlier quoted context omitted.

Compiling to NaCl or asm.js doesn't make an arbitrary C program memory safe. It "merely" prevents any memory safety failure to affect anything outside the container. This is different from, for example, java bytecode which is verified and guaranteed to be memory safe. This is not a mere technicality: an heartbleed vulnerable version of openssl compiled on top of asm.js or NaCl would still leak secret information. edi…

Both asm.js and NaCl guarantee execution stack integrity and allow jumps only at predefined targets in code making exploiting bugs like this highly problematic. Data-only exploits are hard and in asm.js case they are father limited as access outside of the memory leads to program termination. On the other hand memory safety does not prevent bugs like Heartbleed or resent OpenSSH key leak. As the underling issue is re…

Sure, but these are (very effective) mitigation techniques, but still do not guarantee memory safety.

You are right that Heartbleed is not a memory safety issue, I should have been more careful. I just wanted an example of an exploit that doesn't need to escape the process boundary to cause damage.

Re: Glibc getaddrinfo stack-based buffer overflow

#469

Earlier quoted context omitted.

Which is quite justified, as with more modern programming languages, these sorts of bugs are much less likely to happen.

Are they? We have no way to know as no modern language has the reach and widespread usage of something like C. As much as I'd like to think Rust is a nice option for the future, everything leads me to believe that if it ever gets as widespread as C you will have the same caveats, because the main issue is not the language but the programmers using it. No amount of hand holding and safety will prevent bad practices fr…

> Are they?

Yes, they are.

> We have no way to know as no modern language has the reach and widespread usage of something like C.

None needs to have that widespread usage for us to see this. Many bugs in C code causing big security issues are impossible to make in more modern programming languages. Sure, you can make other security issues, of course you can. But the net result is less security issues.

> the main issue is not the language but the programmers using it.

All bugs are caused by programmers making mistakes, but that doesn't mean the language isn't an issue. A language which requires more effort to write correct and secure programs is an inferior language. A language with a long list of situations where the compiler will silently invoke unpredictable behaviour, a list any programmer will sometimes fail to fully account for, is an inferior language.

Re: Glibc getaddrinfo stack-based buffer overflow

#470

Earlier quoted context omitted.

It's better. The musl version is slightly smaller and tidier but also doesn't handle all the same proticols so it's not a fair comparison. At least it doesn't have a lot of conditional compilation and macros. But the musl code too has bloody ZERO comments for a nearly 100 line long method of dense/opaque C code! Why? Is commenting and splitting code into functions frowned upon in "traditional" systems programming? Wh…

I feel like comments are extremely valuable in API documentation, but not so much in the implementation. When you're reading an API you want to understand how it works without cracking open the source. When you're looking at an implementation it is your duty to load the source into your comprehension, at which point comments become irrelevant, or worse, misleading.

Here is how much comments is actually needed: https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdi...
Post reply on HN