繁体   English   中英

如何判断我的内存是否已被PHP应用程序安全释放?

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

这可能更适合security.stackexchange.com,但我特别好奇PHP。

我在应用程序中使用openssl,我注意到openssl资源的免费操作。 这很可能只是一个通用的内存版本,但鉴于加密性质,它可以作为特殊情况处理。

应用程序空间内的AFAIK无法确保从内存中删除变量。 但是,在Zend的土地上,C扩展是否会清除已知的敏感数据,还是只释放内存? openssl_pkey_free是否openssl_pkey_free释放内存? 我怎样才能断言它已被安全发布以将其应用于我将来可能会对其他扩展程序?

我不是安全分析师,所以我对安全的定义相当含糊。

TL; DR:不。

在我看之前,我的答案是:由于PHP是一种动态语言,你应该假设它在被证明不是之前就不会被清除 (例如使用Volatility)。 根据前FreeBSD安全官Colin Percival的说法, “归零缓冲区不足” - 所以它甚至可能都不重要。

但这是一个令人难以置信的无聊答案。 引擎盖下有什么?

openssl_pkey_free()有什么作用?

openssl_pkey_free()由PHP在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
}

如您所见,它调用一个名为EVP_PKEY_free()的函数,该函数由/crypto/evp/p_lib.c#L376中的openssl定义:

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);
}

它会进行一些健全性检查,然后调用OPENSSL_free() ,它只是CRYPTO_free() 的别名

最后, CRYPTO_free() 在这里定义:

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);
}

它似乎只是在典型的情况下调用free_func() ,它是一个指向free()的指针。 在这些操作中,我没有看到任何将内存清零的尝试。

但我真的想在PHP中将内存归零。 我怎样才能?!

如果您可以安装PECL扩展, libsodium安全内存分配实用程序外还提供\\Sodium\\memzero()

请记住,归零内存是一种缓解策略,用于何时发生折衷。 如果您的PHP代码可以从磁盘(或从数据库)读取私钥,攻击者可能会重放代码并直接窃取密钥。 防止这种情况的方法是将密钥存储在硬件安全模块中 ,不要直接触摸它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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