Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to recover secret data with allocating memory (like RSA private key in free'd memory used for decryption)?

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?

like image 888
İbrahim İpek Avatar asked Jul 17 '19 13:07

İbrahim İpek


2 Answers

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).

like image 118
dbush Avatar answered Oct 18 '22 19:10

dbush


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.

like image 39
Nick Reed Avatar answered Oct 18 '22 19:10

Nick Reed