php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76542 Memory leak during verify_peer_name validation of a SAN SSL certificate
Submitted: 2018-06-28 22:20 UTC Modified: -
From: php at lvl dot fastmail dot com Assigned:
Status: Open Package: OpenSSL related
PHP Version: 7.2.7 OS: Ubuntu 18.04
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2018-06-28 22:20 UTC] php at lvl dot fastmail dot com
Description:
------------
Originally discovered here: https://github.com/reactphp/http-client/issues/134. Verified with version 7.2.7-1+ubuntu18.04.1+deb.sury.org+1 on Ubuntu 18.04, libssl 1.1.0g.

There's a memory leak in PHP's validation of SSL certificates when that SSL certificate contains SAN entries. Since nearly every real world SSL certificate uses SAN, this means every long-running PHP script that acts as a HTTPS client will eventually run out of memory.

To reproduce, first create a self-signed certificate with SAN:

openssl req \
    -newkey rsa:2048 \
    -x509 \
    -nodes \
    -keyout server.key \
    -new \
    -out server.crt \
    -subj /CN=127.0.0.1 \
    -reqexts SAN \
    -extensions SAN \
    -config <(cat /etc/ssl/openssl.cnf \
        <(printf '[SAN]\nsubjectAltName=DNS:127.0.0.1,DNS:127.0.0.2')) \
    -sha256 \
    -days 3650

Then configure for example nginx to use this certificate:

server {
    listen 443 ssl;
    ssl_certificate /etc/nginx/server.crt;
    ssl_certificate_key /etc/nginx/server.key;
    return 201;
}

Finally run the test script below and observe using "top" that PHP's memory usage is quickly increasing. Calls to memory_get_usage() will *not* show signs of the leak though.

Running this test with a SSL certificate without the subjectAltName entry will *not* trigger the memory leak.

Add ['verify_peer_name' => false] to the ssl context options and there will *not* be a leak.

Test script:
---------------
<?php
$options = [
    'ssl' => [
        'verify_peer' => false
    ]
];

while (true) {
    $response = file_get_contents('https://127.0.0.1', false, stream_context_create($options));
}


Patches

Add a Patch

Pull Requests

Add a Pull Request

 
PHP Copyright © 2001-2018 The PHP Group
All rights reserved.
Last updated: Tue Oct 16 15:01:25 2018 UTC