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 this is not your bug, you can add a comment by following this link.
If this is your bug, but 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

Add a Patch

Pull Requests

Add a Pull Request

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-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 21:01:27 2024 UTC