5

For example, lets take the pseudo code which tries to obtain RSA private key once stored in allocated (then free'd) memory with this method:

int main(){
    bigNum priKey;


    while(true) {
        void *mem = malloc(2024); //allocate a good amount of chunk

        if(rsaKeyIn(mem, &priKey))
            break;
    }

    printf("RSA PRK found: %s", priKey.getText())

    return 0;
}

Question: Is this possible? or is it possible to recover any other secret data?

Or does the OS zero'es the free'd memory for sake of security? If it is not the case, should we fill allocated memory with zeroes manually before we free it?

Rex5
  • 771
  • 9
  • 23
  • 2
    Zeroing would be a safe thing to do, yes. I believe that all current OSes do zero your memory before giving it to another process (but they might no guerantee that behavior...), but certainly you also want to protect your process from itself. – Linuxios Jul 17 '19 at 13:45
  • 2
    See some notes at this question: https://stackoverflow.com/questions/1287180/why-doesnt-free-zero-out-the-memory-prior-to-releasing-it – Linuxios Jul 17 '19 at 13:48
  • 3
    Note, that `memset` might be insufficient for this, as it is not guaranteed to not be optimized out. There is (optionally) `memset_s` which has the required guarantee. – Eugene Sh. Jul 17 '19 at 13:49

3 Answers3

4

It is possible, since freeing memory doesn't necessarily mean that it gets cleared.

For example, given the following code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    int i, len = 20;
    char *p = malloc(len);
    strcpy(p, "this is a test!!");
    printf("&p=%p, p=%s\n", &p, p);
    for (i=0; i<len; i++) {
        printf("%02x ", p[i]);
    }
    printf("\n");
    free(p);
    // undefined behavior below: dereferencing freed memory
    printf("p=%s\n",  p);
    for (i=0; i<len; i++) {
        printf("%02x ", p[i]);
    }
    printf("\n");
    return 0;
}

My system outputs the following:

&p=0x7ffd24e08290, p=this is a test!!
74 68 69 73 20 69 73 20 61 20 74 65 73 74 21 21 00 00 00 00 
p=
00 00 00 00 00 00 00 00 61 20 74 65 73 74 21 21 00 00 00 00 

So if your program had a security flaw that allowed an attacker to take control of it, they could dump the contents of this freed memory and expose sensitive data.

For this reason, memory containing secret data should be wiped as soon as it is no longer needed. The naive approach to this would be to call memset on the block of memory, however many compilers will optimize it out if it sees that the memory is no longer used after that point.

There is a function defined in the C standard called memset_s which is guaranteed not to be optimized out, however not all implementations have it. You'll need to find some library call that will clear memory that won't me optimized out. Libraries like OpenSSL will do this for you when you call their cleanup routines (see this post as a example).

dbush
  • 205,898
  • 23
  • 218
  • 273
3

It's possible, but there's no guarantees.

If you're coding in C, and the target memory was previously allocated by your program, then depending on your implementation, you may or may not get an access violation (Segmentation fault). This answer explains that it's possible to re-access data that's already been freed by the same program that allocated it, as C memory functions don't necessarily return their memory to the OS after it's freed, and may instead keep it around in the process's heap manager, un-zero'd, to re-allcoate it faster. This is implementation-specific, though, and there's no guarantee it will work. If you really want to make sure sensitive data is gone, use memset() before you free it.

As for another program's sensitive data, though, this post on Information Security describes the conditions where it's possible to read another process's data, allocated or otherwise: running your process as root, a child/parent that forked in such a way, or programs using shared memory space. Outside of these conditions, it's probably not possible.

When you allocate memory, the kernel will return anonymous map (memory that is not backed by a file, and is set to zero) with mmap(). This is always zero filled, except in the most specific circumstances (constrained embedded systems). Even then, the kernel has to be compiled specifically to allow this.

Even in the best of circumstances, I doubt it could be done at all, let alone consistently.

Nick Reed
  • 4,989
  • 4
  • 17
  • 37
1

Inside a single process, neither the operating system nor standard C libraries nor other ordinary libraries provide any protection against finding data by examining the contents of freed memory. The routines that allocate and free memory essentially1 work entirely inside the process, and the process, including your code inside the process, has full control over them. (Cryptographic libraries may include special provisions for protecting data when its memory is being freed.)

Outside a single process, all general-purpose multi-user operating systems protect processes by ensuring that any data formerly used by one process is overwritten with safe data (often zeros) before being given to another process.

For the most part, the protections afforded by operating systems assume the memory and other hardware behave ideally as taught in class: That each memory bit contains a zero or a one and nothing else. In practice, hardware is imperfect, and flaws can sometimes be used to get data that should be protected.

Footnotes

1 Generally, memory allocation routines have to have some interaction with the system, such as requesting more memory from the system. But the bulk of the memory management is done inside the process.

Community
  • 1
  • 1
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312