简体   繁体   中英

How can I tell if my memory has been released securely by a PHP application?

This might be better suited for security.stackexchange.com, but I'm curious about PHP in particular.

I'm working with openssl in an application and I notice the free operations for the openssl resources. This could very well just be just a generic release of memory, but given the cryptographic nature it may be handled as a special case.

AFAIK inside the application space there is no way to ensure a variable is deleted from memory. However, in Zend land, do the C extensions clean up known sensitive data, or do they just release the memory? Does openssl_pkey_free release the memory securely? How can I go about making an assertion that it has been released securely to apply it to other extensions I may be curious about in the future?

I'm not a security analyst, so my definition of securely is rather vague.

TL;DR: No.

Before I even look, my answer is: Since PHP is a dynamic language, you should assume it's not cleared until proven otherwise (eg with Volatility). According to former FreeBSD security officer Colin Percival, "Zeroing Buffers is Insufficient" -- so it might not even matter.

But that's an incredibly boring answer. What's under the hood?

What does openssl_pkey_free() do?

openssl_pkey_free() is defined by PHP in ext/openssl/openssl.c#545 :

void EVP_PKEY_free(EVP_PKEY *x)
{
    int i;

    if (x == NULL)
        return;

    i = CRYPTO_add(&x->references, -1, CRYPTO_LOCK_EVP_PKEY);
#ifdef REF_PRINT
    REF_PRINT("EVP_PKEY", x);
#endif
    if (i > 0)
        return;
#ifdef REF_CHECK
    if (i < 0) {
        fprintf(stderr, "EVP_PKEY_free, bad reference count\n");
        abort();
    }
#endif
    EVP_PKEY_free_it(x);
    if (x->attributes)
        sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
    OPENSSL_free(x);
}

static void EVP_PKEY_free_it(EVP_PKEY *x)
{
    if (x->ameth && x->ameth->pkey_free) {
        x->ameth->pkey_free(x);
        x->pkey.ptr = NULL;
    }
#ifndef OPENSSL_NO_ENGINE
    if (x->engine) {
        ENGINE_finish(x->engine);
        x->engine = NULL;
    }
#endif
}

As you can see, it calls a function called EVP_PKEY_free() , which is defined by openssl in /crypto/evp/p_lib.c#L376 :

void EVP_PKEY_free(EVP_PKEY *x)
{
    int i;

    if (x == NULL)
        return;

    i = CRYPTO_add(&x->references, -1, CRYPTO_LOCK_EVP_PKEY);
#ifdef REF_PRINT
    REF_PRINT("EVP_PKEY", x);
#endif
    if (i > 0)
        return;
#ifdef REF_CHECK
    if (i < 0) {
        fprintf(stderr, "EVP_PKEY_free, bad reference count\n");
        abort();
    }
#endif
    EVP_PKEY_free_it(x);
    if (x->attributes)
        sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
    OPENSSL_free(x);
}

It does some sanity checks then calls OPENSSL_free() , which is just an alias for CRYPTO_free() .

Finally, CRYPTO_free() is defined here :

void CRYPTO_free(void *str)
{
    if (free_debug_func != NULL)
        free_debug_func(str, 0);
#ifdef LEVITTE_DEBUG_MEM
    fprintf(stderr, "LEVITTE_DEBUG_MEM:         < 0x%p\n", str);
#endif
    free_func(str);
    if (free_debug_func != NULL)
        free_debug_func(NULL, 1);
}

It seems to just call free_func() in the typical case, which is a pointer to free() . At no point in these operations did I see any attempt to zero out memory.

But I really want to zero memory in PHP. How can I?!

If you can install PECL extensions, libsodium offers \\Sodium\\memzero() in addition to secure memory allocation utilities .

Please remember that zeroing memory is a mitigation strategy for when a compromise happens. If your PHP code can read the private key from disk (or from a database), the attacker can probably replay the code and steal the key directly. The way to protect against this is store your keys in a hardware security module and never touch it directly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM