Live data from Hacker News

Heartbleed in Rust

tedunangst.com

51–60 of 140 posts

Re: Heartbleed in Rust

#51

This is why I get a little uncomfortable when people suggest Rust fixes tons of security issues. Yes, it will fix some of them. No, just because a Rust program compiles doesn't mean that it won't have problems. Rust is _memory safe_. Nothing more, nothing less.

I feel like you're undervaluing memory safety. Memory safety prevents most (all?) exploits that lead to remote code execution. There can still be high level vulnerabilities, but guaranteed memory safety is a huge improvement. Rust's type system can be used to prevent high level attacks too. For instance, if an sql library is set up properly, it can prevent sql injection by requiring inputs be properly sanitized.

Memory safety prevents 3 vulnerabilities that lead to remote code executions, not "most" or "all" of them. They're 3 very common and important vulnerabilities, though.

Re: Heartbleed in Rust

#52
post #2

My take-away: Low-level code will burn you eventually, and unnecessarily low-level code will burn you unnecessarily

It's not low level, though, that was my original misunderstanding. Heartbleed was not a memory safety issue like I incorrectly assumed. It could happen in, say, C#, or Java. In fact, there's probably existing code with the same bug. It's not uncommon to reuse objects in managed code as a performance hack.

Re: Heartbleed in Rust

#53
Well of course this is possible. You can port a bug compatible version of a program to any other language. That is called Turing complete ( and may involve writing a x64 emulator in VB Script). /snark

A bit more serious, I wonder which security problems Rust would have, if it would be as well studied as C.

Re: Heartbleed in Rust

#54
post #2

My take-away: Low-level code will burn you eventually, and unnecessarily low-level code will burn you unnecessarily

It's not low level, though, that was my original misunderstanding. Heartbleed was not a memory safety issue like I incorrectly assumed. It could happen in, say, C#, or Java. In fact, there's probably existing code with the same bug. It's not uncommon to reuse objects in managed code as a performance hack.

I'd argue that that's a bit low-level, actually. If you're starting to manage your own memory like that then you're still at a higher level than C, but not as high-level as the functional languages, for example.

Honestly, if the end of your collection is beyond the addresses of that collection's valid data then you've just malloc'ed. Is it worth the bugs?

How to malloc in a high-level language(assuming a typecast always succeeds): 1. Make a reference in main (this way it's object will never be garbage collected) 2. Make this reference to an array of objects(hereafter referred to as the "block"), where each object holds n integers. 3. Whenever you wish to save an object to the block, cast it to the class which the block contains and cast from that class when you want to retrieve one.

Is the above idea good for performance? Possibly. Does it belong in a cryptography library/program? Nope.

Re: Heartbleed in Rust

#55
post #43
post #38

Earlier quoted context omitted.

You could write a custom "allocator" that created a pool of zeroed buffers initially, gave out buffers from that pool and accepted buffers back into that pool, and just didn't zero them in between. That would be perfectly "safe" as far as the language was concerned, and would allow you to reproduce the problem.

You would have to go out of your way to do so and handing out buffers that allow reading them without initialization would be a huge warning sign IMO. If you want performance, you don't have to worry about zeroing anything, just call `.clear()` on a `Vec`. Nobody is saying you can't reproduce Heartbleed's effect in Rust, you just have to actually design for it, be it maliciously or out of misunderstanding of the lang…

You would have to go out of your way to do so and handing out buffers that allow reading them without initialization would be a huge warning sign IMO.

So was doing that in the original C code, but no-one noticed.

Re: Heartbleed in Rust

#56
post #14

I mostly agree with the premise: logic errors are always going to be there, at least until the compiler is an IA strong enough to catch them for us (and by then we probably won't need coders anyway...). There's no silver bullet, bad coders are always going to produce. And I also don't like it when people claim that bug X or vulnerability Y wouldn't have happened if they had been technology Z, they're just begging for…

logic errors are always going to be there, at least until the compiler is an IA strong enough to catch them for us (and by then we probably won't need coders anyway...)

This raises some interesting philosophical questions: will the ultimate judge of correctness be a human or machine? If it's a machine, what is to say that its definition of "correct" is what humans want?

For some reason, this quote comes to mind: "Freedom is not worth having if it does not include the freedom to make mistakes."

Re: Heartbleed in Rust

#57
post #28

Some people wrote a completly new TLS Stack in Ocaml to combat this problem: http://openmirage.org/blog/introducing-ocaml-tls Here a Video about Mirage OS and this TLS Stack from the 31C3. Trustworthy secure modular operating system engineering - http://media.ccc.de/browse/congress/2014/31c3_-_6443_-_en_-_... There goal is to reduce the trusted computing base to a minimal. Rust could deliver some of the same benefits…

That page makes the same mistake I did, which caused Ted to write the article in the first place. There's no memory safety issue at play, at least not in the way memory safety is usually referred to. As the TFA shows, the problem is explicitly reusing the same buffer. I don't think there's a general way to prevent this kind of code.

I guess more than just me assumed Heartbleed was a typical blindly allocate and read, going past the buffer bound. But that's not what happened. Writing the same thing is totally possible in OCaml. And in a safe language with GC, it's not unheard of to reuse objects for performance. So in fact it's perhaps even somewhat probable to end up with a Heartbleed-like bug.

Re: Heartbleed in Rust

#58
If I'm reading the blog code correctly, the error is trusting user input:

    // Rust
    let len = buffer[0] as usize;
    // C
    size_t len = buffer[0];
I'm no Rust hacker, but can I expect the Rust type system to be able to encode some form of tainting? Making the leaky sequence illegal:

    let len = buffer[0] as usize;
    // ERROR ERROR ERROR using unscrubbed user input ERROR ERROR ERROR
    buffer[0 .. len]
How exactly to encode tainting is left as an exercise to the reader :) But ideally it should be able to identify that the buffer is reused between 2 different requests, and that data tainted from second request is used to index an array tainted with data from first request. This seems eery up Rust's alley, given the concurrency / allocation disambiguation support I've read (alas superficially) elsewhere.

Re: Heartbleed in Rust

#59
post #8
post #3

Slightly OT: while trying to understand the vulnerability I came across a Rust question. Why can you do this? let mut outfd = File::create(&outpath); match outfd.write_all(&buffer[0 .. len]) { ... } According to `old_io::File`'s doc[0] it returns an `IoResult ` which is an alias `type IoResult = Result ` i.e. `Result `. How come you can do `write_all` directly on a `Result ` without unwrapping the `File` first? The e…

The explanation is at http://doc.rust-lang.org/std/old_io/#error-handling : IoResult implements a bunch of IO traits so you don't need to unwrap it before using it: > Common traits are implemented for IoResult, e.g. impl Reader for IoResult , so that error values do not have to be 'unwrapped' before use.

[deleted]

Re: Heartbleed in Rust

#60

Earlier quoted context omitted.

I feel like you're undervaluing memory safety. Memory safety prevents most (all?) exploits that lead to remote code execution. There can still be high level vulnerabilities, but guaranteed memory safety is a huge improvement. Rust's type system can be used to prevent high level attacks too. For instance, if an sql library is set up properly, it can prevent sql injection by requiring inputs be properly sanitized.

I value it very highly, otherwise, I wouldn't work on Rust. :) I'm just very careful to not suggest that memory safety is the end-all, be-all of errors. The Rust compiler will help you out, but it's certainly not perfect.

Even if it was perfect, nothing can help you if you choose to specifically choose to share data. It was my fault for having only skimmed the original Heartbleed explanation and just made the assumption it was a memory safety issue. Sorry for making Rust look bad, especially right when y'all are working so hard on 1.0.
Post reply on HN