|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull Requests
Pull requests:
HistoryAllCommentsChangesGit/SVN commits
[2016-09-12 04:27 UTC] stas@php.net
[2016-09-12 04:30 UTC] nguyenvuhoang199321 at gmail dot com
[2016-09-12 04:38 UTC] stas@php.net
-PHP Version: 7.0.10
+PHP Version: 5.6.25
-Assigned To:
+Assigned To: stas
[2016-09-12 04:38 UTC] stas@php.net
[2016-09-12 06:30 UTC] nguyenvuhoang199321 at gmail dot com
[2016-09-13 04:04 UTC] stas@php.net
[2016-09-13 04:04 UTC] stas@php.net
-Status: Assigned
+Status: Closed
[2016-09-13 04:06 UTC] stas@php.net
[2016-09-13 04:09 UTC] stas@php.net
[2016-09-13 04:11 UTC] stas@php.net
[2016-09-13 09:02 UTC] ab@php.net
[2016-09-15 09:30 UTC] tyrael@php.net
[2016-10-17 10:08 UTC] bwoebi@php.net
[2016-10-17 10:08 UTC] bwoebi@php.net
[2017-10-16 02:18 UTC] stas@php.net
-CVE-ID:
+CVE-ID: needed
[2019-02-10 01:53 UTC] stas@php.net
-CVE-ID: needed
+CVE-ID:
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 10:00:01 2025 UTC |
Description: ------------ There was a security code in phar_parse_tarfile ``` if (FAILURE == phar_verify_signature(fp, php_stream_tell(fp) - size - 512, myphar->sig_flags, buf + 8, size - 8, fname, &myphar->signature, &myphar->sig_len, error)) { if (error) { char *save = *error; spprintf(error, 4096, "phar error: tar-based phar \"%s\" signature cannot be verified: %s", fname, save); efree(save); } goto bail; } ``` There are no checking *entry.uncompressed_filesize* attacker can create a signature.bin with size less than 8 and then this value is passed to *phar_verify_signature* as sig_len as you can see `entry.uncompressed_filesize - 8` as result sig_len is overflow. And the third param is sig buffer as you can see `sig + 8`, because *entry.uncompressed_filesize* is less than 8 by default emalloc will return 16 bytes this result may lead to heap out of bound. tarfile : https://drive.google.com/open?id=0B0D1DYQpkA9UVkV1Q0tTeGpVYk0 Test script: --------------- <?php $phar = new PharData('phars/signature.tar'); var_dump($phar); ?> Actual result: -------------- This debug steps I will show the malicious parse phar tarfile. Set breakpoint at line 266 in tar.c [----------------------------------registers-----------------------------------] RAX: 0x4 RBX: 0x0 RCX: 0x0 RDX: 0xb ('\x0b') RSI: 0xc ('\x0c') RDI: 0x7fffffffa6ec ("00000000004") RBP: 0x7fffffffa8b0 --> 0x7fffffffae00 --> 0x7fffffffaea0 --> 0x7fffffffaf10 --> 0x7fffffffafa0 --> 0x7fffffffb090 --> 0x7fffffffb0e0 --> 0x7fffffffb110 --> 0x7fffffffb150 --> 0x7fffffffb260 --> 0x7fffffffd560 --> 0x7fffffffe8e0 --> 0x7fffffffea30 --> 0xa1a0a0 (<__libc_csu_init>: push r15) RSP: 0x7fffffffa400 --> 0x7fffffffaff0 --> 0x0 RIP: 0x6e67b5 (<phar_parse_tarfile+1101>: cmp DWORD PTR [rbp-0x468],0x0) R8 : 0xf2b910 ("/home/vagrant/Sources_Ext/audit/src/php7.0-7.0.8/ext/phar/tar.c") R9 : 0xf4 R10: 0x180 R11: 0x7ffff67e2730 --> 0xfffda400fffda12f R12: 0x42c280 (<_start>: xor ebp,ebp) R13: 0x7fffffffeb10 --> 0x2 R14: 0x7ffff3e14030 --> 0x7ffff3e7d040 --> 0x9a66aa (<ZEND_DO_FCALL_SPEC_HANDLER>: push rbp) R15: 0x7ffff3e7d040 --> 0x9a66aa (<ZEND_DO_FCALL_SPEC_HANDLER>: push rbp) EFLAGS: 0x297 (CARRY PARITY ADJUST zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x6e67a3 <phar_parse_tarfile+1083>: mov DWORD PTR [rbp-0x3f0],eax 0x6e67a9 <phar_parse_tarfile+1089>: mov eax,DWORD PTR [rbp-0x3f0] 0x6e67af <phar_parse_tarfile+1095>: mov DWORD PTR [rbp-0x47c],eax => 0x6e67b5 <phar_parse_tarfile+1101>: cmp DWORD PTR [rbp-0x468],0x0 0x6e67bc <phar_parse_tarfile+1108>: jne 0x6e67fd <phar_parse_tarfile+1173> 0x6e67be <phar_parse_tarfile+1110>: mov rax,QWORD PTR [rbp-0x438] 0x6e67c5 <phar_parse_tarfile+1117>: movzx eax,BYTE PTR [rax+0x9c] 0x6e67cc <phar_parse_tarfile+1124>: cmp al,0x67 [------------------------------------stack-------------------------------------] 0000| 0x7fffffffa400 --> 0x7fffffffaff0 --> 0x0 0008| 0x7fffffffa408 --> 0x7fffffffaf00 --> 0x0 0016| 0x7fffffffa410 --> 0x0 0024| 0x7fffffffa418 --> 0x2900000000 ('') 0032| 0x7fffffffa420 --> 0x7ffff3e75018 ("/vagrant_extend/audit/phars/signature.tar") 0040| 0x7fffffffa428 --> 0x7ffff3e5fa00 --> 0x12bf720 --> 0x8d6fc6 (<php_stdiop_write>: push rbp) 0048| 0x7fffffffa430 --> 0x4f665eff8 0056| 0x7fffffffa438 --> 0x0 [------------------------------------------------------------------------------] Legend: code, data, rodata, value 270 if (!old && (hdr->typeflag == TAR_GLOBAL_HDR || hdr->typeflag == TAR_FILE_HDR)) { gdb-peda$ p size $3 = 0x4 You see here size is only 4 bytes. Set breakpoint before phar_verify_signature at line 304, and then continue [----------------------------------registers-----------------------------------] RAX: 0x7ffff3e5fa00 --> 0x12bf720 --> 0x8d6fc6 (<php_stdiop_write>: push rbp) RBX: 0x7fffffffa678 ("gnature.bin") RCX: 0x7fffffffa678 ("gnature.bin") RDX: 0x10 RSI: 0x0 RDI: 0x7ffff3e5fa00 --> 0x12bf720 --> 0x8d6fc6 (<php_stdiop_write>: push rbp) RBP: 0x7fffffffa8b0 --> 0x7fffffffae00 --> 0x7fffffffaea0 --> 0x7fffffffaf10 --> 0x7fffffffafa0 --> 0x7fffffffb090 --> 0x7fffffffb0e0 --> 0x7fffffffb110 --> 0x7fffffffb150 --> 0x7fffffffb260 --> 0x7fffffffd560 --> 0x7fffffffe8e0 --> 0x7fffffffea30 --> 0xa1a0a0 (<__libc_csu_init>: push r15) RSP: 0x7fffffffa3e0 --> 0x7ffff3e79120 --> 0x0 RIP: 0x6e6a0e (<phar_parse_tarfile+1702>: call 0x6e3c22 <phar_verify_signature>) R8 : 0xfffffffc R9 : 0x7ffff3e75018 ("/vagrant_extend/audit/phars/signature.tar") R10: 0x7ffff6794150 (<__strncmp_sse42+3728>: pslldq xmm2,0x1) R11: 0x0 R12: 0x10 R13: 0x7ffff3e79120 --> 0x0 R14: 0x7ffff3e79118 --> 0x0 R15: 0xfffffffc EFLAGS: 0x212 (carry parity ADJUST zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x6e6a05 <phar_parse_tarfile+1693>: mov rcx,rbx 0x6e6a08 <phar_parse_tarfile+1696>: mov edx,r12d 0x6e6a0b <phar_parse_tarfile+1699>: mov rdi,rax => 0x6e6a0e <phar_parse_tarfile+1702>: call 0x6e3c22 <phar_verify_signature> 0x6e6a13 <phar_parse_tarfile+1707>: add rsp,0x20 0x6e6a17 <phar_parse_tarfile+1711>: cmp eax,0xffffffff 0x6e6a1a <phar_parse_tarfile+1714>: jne 0x6e6a9a <phar_parse_tarfile+1842> 0x6e6a1c <phar_parse_tarfile+1716>: cmp QWORD PTR [rbp-0x4b0],0x0 Guessed arguments: arg[0]: 0x7ffff3e5fa00 --> 0x12bf720 --> 0x8d6fc6 (<php_stdiop_write>: push rbp) arg[1]: 0x0 arg[2]: 0x10 arg[3]: 0x7fffffffa678 ("gnature.bin") arg[4]: 0xfffffffc arg[5]: 0x7ffff3e75018 ("/vagrant_extend/audit/phars/signature.tar") [------------------------------------stack-------------------------------------] 0000| 0x7fffffffa3e0 --> 0x7ffff3e79120 --> 0x0 0008| 0x7fffffffa3e8 --> 0x7ffff3e79118 --> 0x0 0016| 0x7fffffffa3f0 --> 0x7fffffffaff0 --> 0x0 0024| 0x7fffffffa3f8 --> 0x6e69cb (<phar_parse_tarfile+1635>: mov rdx,rax) 0032| 0x7fffffffa400 --> 0x7fffffffaff0 --> 0x0 0040| 0x7fffffffa408 --> 0x7fffffffaf00 --> 0x0 0048| 0x7fffffffa410 --> 0x0 0056| 0x7fffffffa418 --> 0x2900000000 ('') [------------------------------------------------------------------------------] Legend: code, data, rodata, value 0x00000000006e6a0e 305 if (FAILURE == phar_verify_signature(fp, php_stream_tell(fp) - size - 512, myphar->sig_flags, buf + 8, size - 8, fname, &myphar->signature, &myphar->sig_len, error)) { As you can see because siglen is calculated by subtract size by 8 so as result this value is negative number in signed int or large int number in unsigned int. This mistake may lead to heap out of bound