Live data from Hacker News

Heartbleed in Rust

tedunangst.com

21–30 of 140 posts

Re: Heartbleed in Rust

#21

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.

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.

Re: Heartbleed in Rust

#22

No true blogger would wilfully misunderstand a buffer overrun vulnerability in order to score some cheap pageviews. To put it simply, his examples are the equivalent of doing this: unsigned char data[4096]; #define X (*(int *)(&data[0])) #define Y (*(int *)(&data[4])) ... Basically, he's explicitly re-using a buffer, no buffer was overrun. In Rust you will not read something out of a buffer you didn't put there first…

> No true blogger would wilfully misunderstand a buffer overrun vulnerability in order to score some cheap pageviews. You may want to read up on Ted, and realise that when he writes > if we don’t actually understand what vulnerabilities like Heartbleed are he's probably talking about you. > Basically, he's explicitly re-using a buffer, no buffer was overrun. Which is essentially what happened in heartbleed. Heartblee…

In Rust, you cannot ever read uninitialized memory (including allocated memory) without using unsafe code (as can be seen in the original code sample, the Rust buffer, unlike the C buffer, is initially zeroed out). So in safe Rust, what you are describing indeed could not happen. The unsafety would have to be explicit at the caller end: the unsafe within the allocator implementation isn't enough.

Re: Heartbleed in Rust

#23
post #2

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

I thought that it highlights bad programming, which will bug out in any language.

Whenever I'm told there wouldn't be any reason to worry, i have yet another reason to worry.

Re: Heartbleed in Rust

#24
post #7

Wasn't the heartbleed issue that you could trick it into reading past the memory it had allocated? That's different to explicitly reusing memory you've allocated without clearing it in between. The original claim was that rust would prevent the class of errors that caused Heartbleed. No one claimed rust would prevent you from writing a program with a different bug that just happens to exhibit similar behavior. Buffer…

> Wasn't the heartbleed issue that you could trick it into reading past the memory it had allocated?

No.

Heartbleed is this:

1. malloc an input and an output buffer of the size specified by the caller (16 bits, up to 65536 bytes)

2. copy input data into input buffer (as little as 1 byte)

3. copy input buffer to output buffer

4. send output buffer to caller

Neither malloc nor free zero-out their stuff, so when you malloc chances are the garbage you get before filling your buffer is the result of previous memory writes. In heartbleed, each call would return up to 65535 bytes of these likely-previous-memory-writes to the caller.

This was made even more likely because OpenSSL includes an anti-mitigation framework in the form of freelists: while malloc doesn't zero memory by default, various OS have added mitigation techniques e.g. BSD's malloc.conf can wipe allocated buffers. However OpenSSL does its own memory management using freelists, so it reuses previously-allocated buffers for new allocations making it even more likely heartbleed would leak interesting data.

Anyway one of the things which don't occur at any point is reading or writing past a buffer.

Re: Heartbleed in Rust

#25
post #7

Wasn't the heartbleed issue that you could trick it into reading past the memory it had allocated? That's different to explicitly reusing memory you've allocated without clearing it in between. The original claim was that rust would prevent the class of errors that caused Heartbleed. No one claimed rust would prevent you from writing a program with a different bug that just happens to exhibit similar behavior. Buffer…

> Wasn't the heartbleed issue that you could trick it into reading past the memory it had allocated? No. Heartbleed is this: 1. malloc an input and an output buffer of the size specified by the caller (16 bits, up to 65536 bytes) 2. copy input data into input buffer (as little as 1 byte) 3. copy input buffer to output buffer 4. send output buffer to caller Neither malloc nor free zero-out their stuff, so when you mal…

Thank you for clarifying.

Re: Heartbleed in Rust

#26

Earlier quoted context omitted.

> No true blogger would wilfully misunderstand a buffer overrun vulnerability in order to score some cheap pageviews. You may want to read up on Ted, and realise that when he writes > if we don’t actually understand what vulnerabilities like Heartbleed are he's probably talking about you. > Basically, he's explicitly re-using a buffer, no buffer was overrun. Which is essentially what happened in heartbleed. Heartblee…

In Rust, you cannot ever read uninitialized memory (including allocated memory) without using unsafe code (as can be seen in the original code sample, the Rust buffer, unlike the C buffer, is initially zeroed out). So in safe Rust, what you are describing indeed could not happen. The unsafety would have to be explicit at the caller end: the unsafe within the allocator implementation isn't enough.

> So in safe Rust, what you are describing indeed could not happen.

Read the last paragraph. OpenSSL has a buffer reuse system via a freelist (and the non-freelist code had bitrotted), it didn't release buffers to the system's allocator after use, buffers were initialised across calls.

Otherwise while heartbleed would still have existed to a large extent, it would also have been mitigable by e.g. malloc.conf or shimming in a zeroing malloc.

Re: Heartbleed in Rust

#27

Earlier quoted context omitted.

In Rust, you cannot ever read uninitialized memory (including allocated memory) without using unsafe code (as can be seen in the original code sample, the Rust buffer, unlike the C buffer, is initially zeroed out). So in safe Rust, what you are describing indeed could not happen. The unsafety would have to be explicit at the caller end: the unsafe within the allocator implementation isn't enough.

> So in safe Rust, what you are describing indeed could not happen. Read the last paragraph. OpenSSL has a buffer reuse system via a freelist (and the non-freelist code had bitrotted), it didn't release buffers to the system's allocator after use, buffers were initialised across calls. Otherwise while heartbleed would still have existed to a large extent, it would also have been mitigable by e.g. malloc.conf or shimm…

I believe if it went through any of Rust's planned custom allocator system (i.e. worked through `box`) it would still not work, though.

You could certainly rewrite exactly the same system from C, of course (though as I noted elsewhere, it seems less likely that OpenSSL would want to replace jemalloc than the often-slow system allocator), but I think it would be quite difficult to write a safe implementation that worked with Rust's borrow checker. The closest thing to a custom allocator that works in Rust right now is an arena with a free list, which requires you to explicitly initialize any newly allocated elements. As another commentor noted, you would really have to go quite far out of your way to reproduce the issue.

Re: Heartbleed in Rust

#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 to writing highperformance low level code.

Re: Heartbleed in Rust

#29

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.

this is especially incredible because the heartbleed bug was a violation of memory safety. the buffer being read from was of a size N, but you could read M bytes from it, where M > N (and in fact, MUCH greater).

Re: Heartbleed in Rust

#30
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…

Is this logic error or just misuse of memory? (The buffer array)
Post reply on HN