4 ms·
It's funny that you mention buffer overflows. An interesting thing to point out—and I'm not sure if anyone has; I've looked before—is that if you follow Meredi
by carussell 9y ago
It's funny that you mention buffer overflows. An interesting thing to point out—and I'm not sure if anyone has; I've looked before—is that if you follow Meredith Patterson's line of reasoning about langsec for protocols in particular, you end up at the conclusion that C-style, NUL-terminated strings are the right way to do things.
This doesn't mean there aren't other defects in the apparatus where C exploits thrive. It's just that (if you adhere to the langsec school of thought) you are required to confront the conclusion that it's been pinned on the wrong thing.
- richardwhiuk 9y agoWhy are C style buffers any more correct than Pascal strings?
- noblethrasher 9y agoLangSec says that we should use the weakest model of computation that can get the job done. Patterson specifically recommends hewing to regular expressions as much as possible, but otherwise going no higher than deterministic context-free for ordinary programs. Null-terminated strings can be recognized by a regular expression, but once you introduce a length field, you (theoretically) need at least a context-sensitive grammar, which is excessively powerful (read: difficult to reason about) for ordinary programs, according to LangSec.
- jerf 9y agoWhere theory and reality diverge, I choose to believe reality. A theory that says null-terminated strings are more secure than length-delimited ones is a theory that needs to be taken back to the shop and examined for why it is wrong. I can imagine a much, much richer theory that might produce "in a perfect world that didn't have any other errors, null-terminated strings would be better". For instance, while this is far from the only problem with null-terminated strings, a lot of their badness historically came from the mistake of mixing stack string data with stack values that say where to return, or mixing the strings with places where you can also put executable code. In a world that had a different kind of stack, null-terminated strings would be less bad. But they would still be bad enough that length-delimited would still be better from a security point of view. And theories of security that are this sensitive to the mistakes around them aren't very useful in the real world, where mistakes will abound and useful security theories need to be able to degrade with some grace whenever possible.
- hisham_hm 9y agoThat depends on what you mean by "getting the job done". If what you want is to write a reference description of a protocol for a paper, and make mathematical proofs of the protocol's properties, that's one thing. (The weakest model of computation there means you'll spend less proof effort around your surroundings -- language, environment -- and more on the protocol, giving you less leeway for error). If you want to write a real-world implementation of the protocol, then the story is different, because the complexities of the real world are unavoidable. You will add complexity to your toolset, to deal with the aspects of the environment that you abstracted away in your paper. When we write proofs for papers about type systems, we use ultra-simple languages like some typed variants of lambda calculus, which are the simplest thing that gets the job done. But once the type properties are proved, no one is expected to write their real programs that way -- they are expected to replicate those properties in the real world instead.
- amaranth 9y agoI suspect it's because they can't get out of sync in a way that causes OOB reads. You could have the null too early in the buffer but can't have it too late. With Pascal strings you could have a buffer of size 18 but with a length tag of 30 and have no way to know you're going overflow.
- TimJYoung 9y agoIn terms of a buffer overflow, how would any of that make any difference ? If you somehow manage to overwrite the length prefix due to some shoddy pointer manipulation (and buffer writes) and, subsequently, write past the end of the string buffer, how is that different from just writing past the end of the string buffer in the first place ? With Pascal strings, you at least have a fighting chance in terms of knowing the actual size of the buffer.
- EtDybNuvCu 9y agoThis is naïve first-order thinking; we can justify length-prefixed strings on a more abstract basis. First, note that in a trusted kernel, we'll prefer to define our string-handling functions only once and then explicitly hand-write their correctness proofs. This means that, on a higher level, we do not have to prefer any one particular string abstraction just because of the white-box implementation details; we'll call strcat() either way. Now, note that we can store any character, including NUL, in a length-prefixed string. However, we cannot do this in NUL-terminated strings. This is because stray NULs will change the apparent length of the string. More directly, what a string is, whether it's "string of length 5" or "string of length 255", is determined by the string's data. In contrast, a length-prefixed string contains two fields, and only one of them controls the length of the string. Now, imagine that an attacker comes to totally control the contents of our string. In the NUL-terminated scenario, they also control the length of the string! This does not occur with length-prefixed strings. There is strictly less capability offered to the attacker. I know about the automaton-based approach to langsec, but this capability-based analysis is far more in line with the recent rise of weird machines.