php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80747 Providing RSA key size < 512 generates key that crash PHP
Submitted: 2021-02-13 19:44 UTC Modified: 2021-02-15 14:16 UTC
From: ondrej@php.net Assigned:
Status: Closed Package: Reproducible crash
PHP Version: 8.0.2 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: ondrej@php.net
New email:
PHP Version: OS:

 

 [2021-02-13 19:44 UTC] ondrej@php.net
Description:
------------
When openssl_pkey_new() is provided with keysize smaller than 512, it will return object that will crash PHP (in OpenSSL `BN_num_bits()`):

```
#0  0x00007ffff79cb711 in BN_num_bits () from /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
#1  0x00005555556a123d in zif_openssl_pkey_get_details (execute_data=<optimized out>, return_value=0x7ffff54130a0) at ./ext/openssl/openssl.c:4510
#2  0x00005555558768b1 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER () at ./Zend/zend_vm_execute.h:1295
#3  execute_ex (ex=0x0) at ./Zend/zend_vm_execute.h:54528
#4  0x000055555587c51c in zend_execute (op_array=0x7ffff548a000, return_value=0x0) at ./Zend/zend_vm_execute.h:58875
#5  0x00005555558136ed in zend_execute_scripts (type=-180277216, type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at ./Zend/zend.c:1680
#6  0x00005555557b044b in php_execute_script (primary_file=primary_file@entry=0x7fffffffce00) at ./main/main.c:2488
#7  0x00005555558a1e1e in do_cli (argc=2, argv=0x555555a34eb0) at ./sapi/cli/php_cli.c:949
#8  0x000055555566759b in main (argc=2, argv=0x555555a34eb0) at ./sapi/cli/php_cli.c:1336
```

The earliest version I can reproduce this is 7.0;

Test script:
---------------
<?php

$ssl = openssl_pkey_new (array('config' => '/etc/ssl/openssl.cnf', 'private_key_bits' => 511));
print_r(openssl_pkey_get_details($ssl));

?>

Expected result:
----------------
```
Array
(
    [bits] => 512
    [key] => -----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL8nDEgxSViozYDoAq1cDy7O693l8BPm
c52VCAKkJ93MgSWla35FlmVVunakjgkX2V3RXr48XBUTngi1KyGF0NsCAwEAAQ==
-----END PUBLIC KEY-----

    [rsa] => Array
        (
[...]
        )

    [type] => 0
)
```

Actual result:
--------------
#0  0x00007ffff79cb711 in BN_num_bits () from /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
No symbol table info available.
#1  0x00005555556a123d in zif_openssl_pkey_get_details (execute_data=<optimized out>, return_value=0x7ffff54130a0) at ./ext/openssl/openssl.c:4510
        key = 0x7ffff5413170
        pkey = 0x555555c2d880
        out = 0x555555c285f0
        pbio_len = 85
        pbio = 0x555555c28850 "-----BEGIN PUBLIC KEY-----\nMBQwDQYJKoZIhvcNAQEBBQADAwAwAA==\n-----END PUBLIC KEY-----\nU"
        ktype = <optimized out>
#2  0x00005555558768b1 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER () at ./Zend/zend_vm_execute.h:1295
        call = 0x7ffff5413120
        fbc = 0x555555c29730
        ret = 0xfffffffe00000008
        retval = {value = {lval = <optimized out>, dval = <optimized out>, counted = <optimized out>, str = <optimized out>, arr = <optimized out>, obj = <optimized out>, res = <optimized out>, ref = <optimized out>, ast = <optimized out>, zv = <optimized out>, ptr = <optimized out>, ce = <optimized out>, func = <optimized out>, ww = {w1 = <optimized out>, w2 = <optimized out>}}, u1 = {type_info = <optimized out>, v = {type = <optimized out>, type_flags = <optimized out>, u = {extra = <optimized out>}}}, u2 = {next = <optimized out>, cache_slot = <optimized out>, opline_num = <optimized out>, lineno = <optimized out>, num_args = <optimized out>, fe_pos = <optimized out>, fe_iter_idx = <optimized out>, access_flags = <optimized out>, property_guard = <optimized out>, constant_flags = <optimized out>, extra = <optimized out>}}
        call_info = 1436668864
        call = <optimized out>
        fbc = <optimized out>
        ret = <optimized out>
        retval = {value = {lval = <optimized out>, dval = <optimized out>, counted = <optimized out>, str = <optimized out>, arr = <optimized out>, obj = <optimized out>, res = <optimized out>, ref = <optimized out>, ast = <optimized out>, zv = <optimized out>, ptr = <optimized out>, ce = <optimized out>, func = <optimized out>, ww = {w1 = <optimized out>, w2 = <optimized out>}}, u1 = {type_info = <optimized out>, v = {type = <optimized out>, type_flags = <optimized out>, u = {extra = <optimized out>}}}, u2 = {next = <optimized out>, cache_slot = <optimized out>, opline_num = <optimized out>, lineno = <optimized out>, num_args = <optimized out>, fe_pos = <optimized out>, fe_iter_idx = <optimized out>, access_flags = <optimized out>, property_guard = <optimized out>, constant_flags = <optimized out>, extra = <optimized out>}}
        call_info = <optimized out>
#3  execute_ex (ex=0x0) at ./Zend/zend_vm_execute.h:54528
        vm_stack_data = {orig_opline = 0x7fffffffce00, orig_execute_data = 0x8, hybrid_jit_red_zone = '\000' <repeats 15 times>}
#4  0x000055555587c51c in zend_execute (op_array=0x7ffff548a000, return_value=0x0) at ./Zend/zend_vm_execute.h:58875
        execute_data = 0x7ffff5413020
        object_or_called_scope = <optimized out>
        call_info = <optimized out>
#5  0x00005555558136ed in zend_execute_scripts (type=-180277216, type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at ./Zend/zend.c:1680
        files = {{gp_offset = 40, fp_offset = 1, overflow_arg_area = 0x7fffffffa9e0, reg_save_area = 0x7fffffffa970}}
        i = 1
        file_handle = 0x7ffff548f0e0
        op_array = 0x7ffff548a000
        ret = SUCCESS
#6  0x00005555557b044b in php_execute_script (primary_file=primary_file@entry=0x7fffffffce00) at ./main/main.c:2488
        realfile = "/tmp/y.php\000\000\000\000\000\000/tmp", '\000' <repeats 12 times>, "\006\000\000\000\000\000\000\000\214\214q\367\377\177\000\000\200+~\367\377\177\000\000\200\000\000\000\000\000\000\000\220\000\000\000\000\000\000\000\271\373j\367\377\177\000\000\240\000\000\000\000\000\000\000\314\321j\367\377\177\000\000\b\000\000\000\062\000\000\000\314\321j\367\377\177\000\000\002", '\000' <repeats 15 times>, "\001\000\000\000\000\000\000\000\060\000\000\000\000\000\000\000\060\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\003\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\004\000\000\000\061", '\000' <repeats 11 times>, "\003\000\000\000\060\000\000\000"...
        __orig_bailout = <optimized out>
        __bailout = {{__jmpbuf = {93824997347000, 8584373253184256353, 93824996105344, 93824996105384, 1, 93824997347056, 8584373250067888481, 2482755480110201185}, __mask_was_saved = 0, __saved_mask = {__val = {0 <repeats 16 times>}}}}
        prepend_file_p = 0x0
        append_file_p = 0x0
        prepend_file = {handle = {fp = 0x0, stream = {handle = 0x0, isatty = 0, reader = 0x0, fsizer = 0x0, closer = 0x0}}, filename = 0x0, opened_path = 0x0, type = ZEND_HANDLE_FILENAME, free_filename = false, buf = 0x0, len = 0}
        append_file = {handle = {fp = 0x0, stream = {handle = 0x0, isatty = 0, reader = 0x0, fsizer = 0x0, closer = 0x0}}, filename = 0x0, opened_path = 0x0, type = ZEND_HANDLE_FILENAME, free_filename = false, buf = 0x0, len = 0}
        old_cwd = 0x7fffffffa9e0 ""
        use_heap = false
        retval = 0
#7  0x00005555558a1e1e in do_cli (argc=2, argv=0x555555a34eb0) at ./sapi/cli/php_cli.c:949
        __orig_bailout = 0x7fffffffe040
        __bailout = {{__jmpbuf = {0, -8584373251475932831, 0, 0, 140737488347192, 140737488347188, 8584373253182159201, 2482755625756490081}, __mask_was_saved = 0, __saved_mask = {__val = {93824995985191, 93824995985204, 93824995985221, 93824995985242, 93824995985262, 93824995985279, 93824995985300, 93824995985310, 93824995985324, 93824995985346, 93824995985365, 93824995985392, 93824995985421, 93824995985449, 0, 28404036}}}}
        c = <optimized out>
        file_handle = {handle = {fp = 0x555555c28280, stream = {handle = 0x555555c28280, isatty = 0, reader = 0x55555587ed50 <zend_stream_stdio_reader>, fsizer = 0x55555587ee30 <zend_stream_stdio_fsizer>, closer = 0x55555587ed20 <zend_stream_stdio_closer>}}, filename = 0x555555a34ef0 "y.php", opened_path = 0x0, type = ZEND_HANDLE_STREAM, free_filename = false, buf = 0x7ffff547f240 "", len = 146}
        behavior = <optimized out>
        reflection_what = <optimized out>
        request_started = 1
        php_optarg = 0x0
        orig_optarg = 0x0
        php_optind = 2
        orig_optind = 1
        exec_direct = <optimized out>
        exec_run = <optimized out>
        exec_begin = <optimized out>
        exec_end = <optimized out>
        arg_free = <optimized out>
        arg_excp = <optimized out>
        script_file = <optimized out>
        translated_path = 0x555555c284f0 "/tmp/y.php"
        interactive = 0
        param_error = <optimized out>
        hide_argv = <optimized out>
#8  0x000055555566759b in main (argc=2, argv=0x555555a34eb0) at ./sapi/cli/php_cli.c:1336
        __orig_bailout = 0x0
        __bailout = {{__jmpbuf = {93824997144288, -8584373251475932831, 0, 0, 140737488347192, 140737488347188, 8584373252555110753, 2482755317425076577}, __mask_was_saved = 0, __saved_mask = {__val = {640, 656, 140737345629056, 41, 18446744073709550968, 140737345629152, 140737344360908, 4294967295, 140737344360908, 39, 0, 4543, 640, 0, 72704, 140733193388153}}}}
        c = <optimized out>
        exit_status = 0
        module_started = 1
        sapi_started = 1
        php_optarg = 0x0
        php_optind = 1
        use_extended_info = 0
        ini_path_override = 0x0
        ini_entries = 0x555555a35150 "html_errors=0\nregister_argc_argv=1\nimplicit_flush=1\noutput_buffering=0\nmax_execution_time=0\nmax_input_time=-1\n"
        ini_entries_len = 0
        ini_ignore = 0
        sapi_module = <optimized out>

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-02-15 14:16 UTC] nikic@php.net
-Status: Open +Status: Analyzed
 [2021-02-15 14:16 UTC] nikic@php.net
On OpenSSL 1.0.2 or newer we use RSA_generate_key_ex and don't correctly check it for failure (rsaparam is not discarded).
 [2021-02-15 14:35 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=64b10854643531bcf62a884aaea0bafc57e4f914
Log: Fixed bug #80747
 [2021-02-15 14:35 UTC] nikic@php.net
-Status: Analyzed +Status: Closed
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sun Feb 02 16:01:29 2025 UTC