|
|
Log in / Subscribe / Register

Wi-Fi software security bug could leave Android, Windows, Linux open to attack (Ars Technica)

Wi-Fi software security bug could leave Android, Windows, Linux open to attack (Ars Technica)

Posted Apr 26, 2015 9:09 UTC (Sun) by paulj (subscriber, #341)
In reply to: Wi-Fi software security bug could leave Android, Windows, Linux open to attack (Ars Technica) by wahern
Parent article: Wi-Fi software security bug could leave Android, Windows, Linux open to attack (Ars Technica)

I'm not advocating that network protocol parsers should be written in formal, complicated parser generators.

I'm saying it's inexcusable not to use a bounds-checking abstraction layer. E.g. a simple bound-tracking array/stream abstraction, that tracks state such as the length of valid data and the next position to read from. Trivial to write and use.

So, given:

struct foo {
int len;
void *data;
};


instead of something like:

int *buf = <untrusted network input>;
int len = ntohl(buf[0]);
struct foo *foo = malloc (sizeof(struct foo) + len);
foo->len = len;
memcpy (foo->data, buf[1], foo->len);

you instead do something like:

struct barray *buf = barray_new ();
<read network input into the barray>

int len = barray_read4 (buf);
struct foo *foo = malloc (sizeof(struct foo) + len);
foo->len = len;
barray_cpy (foo->data, buf, foo->len);

The former is obviously a giant security hole. The latter way at least can safely abort and turn a remote exploit into (at worst) a DoS, regardless of other problems (e.g. signed length).

This class of bug comes up again, and again, and again (e.g. Heartbleed, this article), yet it's so damn easy to mitigate it. However, it's 2015 and lots of code still isn't doing this. Even if it was originally old, once exploited, the fixes are band-aids and *still* using these generally much more unsafe practices!

It's trivial to add a checked, bounded buffer abstraction when fixing these. Admittedly it's a verbose change to have to make that will touch a good few lines, but you don't need to think much about the changes. Coccinelle could probably handle a lot of the changes!


to post comments

Wi-Fi software security bug could leave Android, Windows, Linux open to attack (Ars Technica)

Posted Apr 27, 2015 20:30 UTC (Mon) by wahern (subscriber, #37304) [Link] (3 responses)

The problem with using a library with specialized data structures is that it complicates crossing interface and component boundaries unless _everybody_ uses that same library.

Count how many "safe string" libraries are out in the wild just for C code. It's ridiculous. The ratio of such libraries to users is probably very near 1.0.

So I still think your suggestion is untenable in the real world.

The particular bug in this instance was a rather glaring unchecked memcpy. Why fantasize about using an automated tool to help refactor _all_ such code to theoretically solve _all_ such problems when well-known and existing automated tools (or even just a rigorous OpenBSD-style audit) could have easily discovered this particular unchecked comparison? _Anybody_ could have done that check without having to push any changes upstream or convince anybody of the superiority of any solution. But few people are.

Basically, it seems to me the heart of the problem isn't lack of tool sophistication. It was simply lack of anybody caring. If people don't care enough to review the code, why would you think adding even more complexity to the equation--which requires solving the cat herding problem--would be even remotely practical?

BTW, as the OpenBSD folks explained, one of the biggest issues in the Heartbleed case was the allocation abstraction layer that OpenSSL used. OpenBSD's normal audit process and bug mitigation measures likely would have caught the bug at it's inception. Which goes to my argument about the benefit of adhering to simplicity and sticking to common interfaces. Even if those interfaces are suboptimal, the fact that everybody is already using them means you benefit from more eyeballs and more sweat equity.

In the context of C code (i.e. excluding better languages--supplementation or wholesale switch) there are only two choices: 1) transparency, or 2) see #1. Transparency requires simple code using least common denominator best practices. It's the most effective way to improve the C ecosystems in _practice_ because it's the most effective way to ensure that your code can be easily audited, either by other humans or with automated tools. This has _proven_ to work better than dreaming and arguing about architecting better solutions.

Wi-Fi software security bug could leave Android, Windows, Linux open to attack (Ars Technica)

Posted Apr 27, 2015 20:42 UTC (Mon) by paulj (subscriber, #341) [Link]

It's hardly untenable, because:

1. A simple bounded, checking buffer is pretty trivial to write. A 1.0 implementation:user ratio is fine, it's so simple. (Or otherwise use Quagga's, though there's a bit of cruft in its one to strip out - but it's not exactly a large or complex bit of code).

2. It's worked pretty for well for Quagga and GNU Zebra before that.

Quagga has had a good number of DoS bugs, which otherwise would have been remote exploits, thanks to it generally using a simple bounded buffer in between IO and parsing. At least, in its 2 most widely used daemons.

There's still a good bit of network facing parsers that don't use that abstraction, but in less widely used stuff usually. Which we have to eradicate.

Wi-Fi software security bug could leave Android, Windows, Linux open to attack (Ars Technica)

Posted Apr 27, 2015 20:50 UTC (Mon) by paulj (subscriber, #341) [Link] (1 responses)

Oh, and on your other point. You're saying we should rely on human eyes catching bugs on parameters to memcpy's not having been checked properly earlier. We know this doesn't work.

Code that relies on humans mentally analysing C parsers of untrusted input to make sure that every bit of pointer arithmetic and memory writes that could be affected by the input will always be safe is code that will have lots of remote exploits. We know this.

If you want to make code secure, you *must* let the computer help you. Even without fancy compilers, it is still trivial for a programmer to place a simple bounded-buffer between the IO and the parser, to ensure that basic constraints like "Don't read or write outside the allocated buffer" are *ALWAYS* met OR the programme terminates *safely*.

It's trivial to do. Why not do it?

Wi-Fi software security bug could leave Android, Windows, Linux open to attack (Ars Technica)

Posted Apr 27, 2015 20:52 UTC (Mon) by paulj (subscriber, #341) [Link]

Oh, and compilers can now also do this instrumentation. GCC 5 has new sanitisers that can I think (mentioned elsewhere). However, I suspect it might still be faster to use an explicit bounded buffer around just the key bits of IO.


Copyright © 2026, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds