Part 2 is correct in that trying to zero memory to "cover your tracks" is an indication that You're Doing It Wrong, but I disagree that this is a language issue. Even if you hand-wrote some assembly, carefully managing where data is stored, wiping registers after use, you still end up information leakage. Typically the CPU cache hierarchy is going to end up with some copies of keys and plaintext. You know that? OK, t…
So is it correct to say that if a process does not want to leak information to other processes with different user ID's running under the same kernel that a necessary (but not necessarily sufficient, due to things like timing attacks) condition is for it to ensure that any allocated memory is zero'd before being free'd ? I wonder if current VM implementations are doing this systematically. It seems like a kernel API…
Zeroing buffers is insufficient
121–130 of 134 posts
Re: Zeroing buffers is insufficient
#122Earlier quoted context omitted.
So is it correct to say that if a process does not want to leak information to other processes with different user ID's running under the same kernel that a necessary (but not necessarily sufficient, due to things like timing attacks) condition is for it to ensure that any allocated memory is zero'd before being free'd ? I wonder if current VM implementations are doing this systematically. It seems like a kernel API…
All kernels I know of zero all memory they hand over to user processes. It's been part of basic security for quite some time - exactly for this kind of thing. It's usually done on allocation, not free - it doesn't really matter which way around, but doing it "lazily" can often be better performance.
It seems like the key though is ensuring that your environment uses distinct non-root users for all security relevant processes so that a security bug in one process doesn't allow the attacker to gain access to others.
EDIT: On second thought there may be some advantage to effectively zeroing memory for security critical data within a process but the likely value add seems low to me. Once a process has been hacked it seems pretty unlikely that you can hope to control what information it leaks.
Re: Zeroing buffers is insufficient
#123Earlier quoted context omitted.
That's what I mean actually getting it consistent is hard as the performance is really hard to predict and may change even with CPU stepping. Even then it requires very solid planning as well.
I think you misunderstand timing sidechannels. The idea is that (for example) if you compare two strings with length 15 you compare all 15 chars regardless if you find that the 3th char is already different. You only need to be consistent with yourself. Stepping is completely irrelevant here.
I don't :) Basically you want all the code branches to result in similar (same) timings. Basic on the CPU and the data inputs those timing would vary, hence assembly alone won't do.
Re: Zeroing buffers is insufficient
#124 #include
void bar(void *s, size_t count)
{
memset(s, 0, count);
__asm__ ("" : "=r" (s) : "0" (s));
}
int main(void)
{
char foo[128];
bar(foo, sizeof(foo));
return 0;
}
gcc -O2 -o foo foo.c -g
gdb ./foo
...
(gdb) disassemble main
Dump of assembler code for function main:
0x00000000004003d0 : sub $0x88,%rsp
0x00000000004003d7 : mov $0x80,%esi
0x00000000004003dc : mov %rsp,%rdi
0x00000000004003df : callq 0x400500
0x00000000004003e4 : xor %eax,%eax
0x00000000004003e6 : add $0x88,%rsp
0x00000000004003ed : retq
End of assembler dump.
(gdb) disassemble bar
Dump of assembler code for function bar:
0x0000000000400500 : sub $0x8,%rsp
0x0000000000400504 : mov %rsi,%rdx
0x0000000000400507 : xor %esi,%esi
0x0000000000400509 : callq 0x4003b0
0x000000000040050e : add $0x8,%rsp
0x0000000000400512 : retq
End of assembler dump.Re: Zeroing buffers is insufficient
#125Earlier quoted context omitted.
All kernels I know of zero all memory they hand over to user processes. It's been part of basic security for quite some time - exactly for this kind of thing. It's usually done on allocation, not free - it doesn't really matter which way around, but doing it "lazily" can often be better performance.
In that case your original comment looks like the way to go and should make pretty much everything else in this thread moot. It seems like the key though is ensuring that your environment uses distinct non-root users for all security relevant processes so that a security bug in one process doesn't allow the attacker to gain access to others. EDIT: On second thought there may be some advantage to effectively zeroing m…
So wiping that sort of information as soon as it becomes unneeded is good hygiene. And I still think it is reasonable to do the least you can to avoid ending up with sensitive data on the disk after a core dump.
Re: Zeroing buffers is insufficient
#126Earlier quoted context omitted.
In that case your original comment looks like the way to go and should make pretty much everything else in this thread moot. It seems like the key though is ensuring that your environment uses distinct non-root users for all security relevant processes so that a security bug in one process doesn't allow the attacker to gain access to others. EDIT: On second thought there may be some advantage to effectively zeroing m…
Actually use of uninitialized memory is a reasonably common flaw and doesn't imply the process has been or can be hacked to execute arbitrary code. So wiping that sort of information as soon as it becomes unneeded is good hygiene. And I still think it is reasonable to do the least you can to avoid ending up with sensitive data on the disk after a core dump.
As for the second point production software isn't typically configured to produce core dumps (ie. ulimit -c 0).
Re: Zeroing buffers is insufficient
#127> For encryption operations these aren't catastrophic things to leak — the final block of output is ciphertext, and the final AES round key, while theoretically dangerous, is not enough on its own to permit an attack on AES This is incorrect. The AES key schedule is bijective, which makes recovering the last round key as dangerous as recovering the first.
How hard is that attack to code? I have a hard time imagining a case where a target leaks just a subkey, so this is one of those things I knew "about" but not "how".
Re: Zeroing buffers is insufficient
#128Earlier quoted context omitted.
Actually use of uninitialized memory is a reasonably common flaw and doesn't imply the process has been or can be hacked to execute arbitrary code. So wiping that sort of information as soon as it becomes unneeded is good hygiene. And I still think it is reasonable to do the least you can to avoid ending up with sensitive data on the disk after a core dump.
Use of uninitialized memory is certainly a common bug but I'm not seeing what that has to do with zeroing free'd memory. It might be easier to detect such a bug if the uninitialized memory is zero'd but it seems like the work devoted to zeroing memory would be better spent fixing the uninitialized memory accesses. As for the second point production software isn't typically configured to produce core dumps (ie. ulimit…
It's a start. Adding the safeguard doesn't mean effort won't be put into fixing the actual bugs. But you just don't fix all the world's bugs overnight. That's why things like virtual memory, permissions, chroots, ASLR, NX, SSP and such exist.
How many systems enable core dumps by default? I don't actually know, but I think quite a few do. Every application you use to get stuff done is a production application. Every application that handles sensitive information handles sensitive information whether it is in production or not. Leaking passwords and keys can be as simple as working on some client software, having it crash once, then passing through airport security and getting your HD snooped on...
Re: Zeroing buffers is insufficient
#129Earlier quoted context omitted.
Use of uninitialized memory is certainly a common bug but I'm not seeing what that has to do with zeroing free'd memory. It might be easier to detect such a bug if the uninitialized memory is zero'd but it seems like the work devoted to zeroing memory would be better spent fixing the uninitialized memory accesses. As for the second point production software isn't typically configured to produce core dumps (ie. ulimit…
It's not so hard to zero memory when it becomes unused. So libraries like LibreSSL do that. Increasingly, other applications are also starting to use this pattern. It is easier to add a few safeguards into the library than it is to fix every past, present and future application that uses it. It's a start. Adding the safeguard doesn't mean effort won't be put into fixing the actual bugs. But you just don't fix all the…
I wonder if it wouldn't make more sense to do a first principles analysis of what needs to be protected and then design mechanisms at the appropriate level of abstraction to ensure that these requirements are met. It seems to me that this is the approach that has been traditionally taken in OS level design and I agree that it hasn't worked very well. But I wonder if that isn't more because applications and environments are not being carefully designed to take advantage of the OS level security mechanisms that already exist.
Personally I would feel more confident depending on a robust kernel level security mechanism than a hodgepodge of application level fixes that depend on everything from compiler optimizations to CPU caching mechanisms.
Re: Zeroing buffers is insufficient
#130Earlier quoted context omitted.
It's not so hard to zero memory when it becomes unused. So libraries like LibreSSL do that. Increasingly, other applications are also starting to use this pattern. It is easier to add a few safeguards into the library than it is to fix every past, present and future application that uses it. It's a start. Adding the safeguard doesn't mean effort won't be put into fixing the actual bugs. But you just don't fix all the…
I understand your point but it seems like this approach ends up making security dependent on an a very deep stack of technology solutions, each rather fragile (as this post and thread demonstrate). I wonder if it wouldn't make more sense to do a first principles analysis of what needs to be protected and then design mechanisms at the appropriate level of abstraction to ensure that these requirements are met. It seems…
In the meanwhile, I do what I can to review, audit, and apply best practices at application level. These are the things we can do here and now. These are things that are already in use to make your system more secure.
You're right that it is a hodgepodge of tricks and never quite perfect or capable of blocking all attacks. In an ideal world someone would design and give us a system that provides perfect security right out of the box, in a small & elegant & easy to understand manner.
I'm not smart enough to do that so I'll only dream of the unicorns. :-)