php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #72928 Out of bound when verify signature of zip phar in phar_parse_zipfile
Submitted: 2016-08-23 07:53 UTC Modified: 2016-09-16 13:39 UTC
From: nguyenvuhoang199321 at gmail dot com Assigned: stas (profile)
Status: Closed Package: PHAR related
PHP Version: 5.6.25 OS: ALL
Private report: No CVE-ID: 2016-7414
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: nguyenvuhoang199321 at gmail dot com
New email:
PHP Version: OS:

 

 [2016-08-23 07:53 UTC] nguyenvuhoang199321 at gmail dot com
Description:
------------
There was a security code in phar_parse_zipfile
```
sig = (char *) emalloc(entry.uncompressed_filesize);
read = php_stream_read(fp, sig, entry.uncompressed_filesize);
if (read != entry.uncompressed_filesize) {
	php_stream_close(sigfile);
	efree(sig);
	PHAR_ZIP_FAIL("signature cannot be read");
}
mydata->sig_flags = PHAR_GET_32(sig);
if (FAILURE == phar_verify_signature(sigfile,
	php_stream_tell(sigfile),
	mydata->sig_flags,
	sig + 8,
	entry.uncompressed_filesize - 8,
	fname,
	&mydata->signature,
	&mydata->sig_len,
	error)
	) {
```
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.

phar zip file : https://drive.google.com/file/d/0B0D1DYQpkA9Ud3I2OFlfeFRqbEU/view?usp=sharing

Test script:
---------------
<?php
	$phar = new PharData('phars/signature.zip');
	var_dump($phar);
?>

Actual result:
--------------
This debug step i will show the malicious parse phar zip.
Set breakpoint at line 419 in zip.c

[----------------------------------registers-----------------------------------]
RAX: 0x4
RBX: 0x13
RCX: 0x0
RDX: 0x1a3
RSI: 0xf2cc38 ("/home/vagrant/Sources_Ext/audit/src/php7.0-7.0.8/ext/phar/zip.c")
RDI: 0x4
RBP: 0x7fffffffa870 --> 0x7fffffffadb0 --> 0x7fffffffae50 --> 0x7fffffffaec0 --> 0x7fffffffaf50 --> 0x7fffffffb040 --> 0x7fffffffb090 --> 0x7fffffffb0c0 --> 0x7fffffffb100 --> 0x7fffffffb210 --> 0x7fffffffd510 --> 0x7fffffffe890 --> 0x7fffffffe9e0 --> 0xa1a0a0 (<__libc_csu_init>:	push   r15)
RSP: 0x7ffffffea600 --> 0x7fffffffafa0 --> 0x0
RIP: 0x6ed786 (<phar_parse_zipfile+7788>:	call   0x911568 <_emalloc>)
R8 : 0x0
R9 : 0xf2cc38 ("/home/vagrant/Sources_Ext/audit/src/php7.0-7.0.8/ext/phar/zip.c")
R10: 0x5
R11: 0x206
R12: 0x42c280 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffeac0 --> 0x2
R14: 0x7ffff3e14030 --> 0x7ffff3e7e040 --> 0x9a66aa (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
R15: 0x7ffff3e7e040 --> 0x9a66aa (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x6ed777 <phar_parse_zipfile+7773>:	mov    edx,0x1a3
   0x6ed77c <phar_parse_zipfile+7778>:	lea    rsi,[rip+0x83f4b5]        # 0xf2cc38
   0x6ed783 <phar_parse_zipfile+7785>:	mov    rdi,rax
=> 0x6ed786 <phar_parse_zipfile+7788>:	call   0x911568 <_emalloc>
   0x6ed78b <phar_parse_zipfile+7793>:	mov    QWORD PTR [rbp-0x101d0],rax
   0x6ed792 <phar_parse_zipfile+7800>:	mov    eax,DWORD PTR [rbp-0x10170]
   0x6ed798 <phar_parse_zipfile+7806>:	mov    edx,eax
   0x6ed79a <phar_parse_zipfile+7808>:	mov    rcx,QWORD PTR [rbp-0x101d0]
Guessed arguments:
arg[0]: 0x4
arg[1]: 0xf2cc38 ("/home/vagrant/Sources_Ext/audit/src/php7.0-7.0.8/ext/phar/zip.c")
arg[2]: 0x1a3
arg[3]: 0x0
arg[4]: 0x0
[------------------------------------stack-------------------------------------]
0000| 0x7ffffffea600 --> 0x7fffffffafa0 --> 0x0
0008| 0x7ffffffea608 --> 0x7fffffffaeb0 --> 0x0
0016| 0x7ffffffea610 --> 0x0
0024| 0x7ffffffea618 --> 0x2900000000 ('')
0032| 0x7ffffffea620 --> 0x7ffff3e70088 ("/vagrant_extend/audit/phars/signature.zip")
0040| 0x7ffffffea628 --> 0x7ffff3e5fa00 --> 0x12bf720 --> 0x8d6fc6 (<php_stdiop_write>:	push   rbp)
0048| 0x7ffffffea630 --> 0x0
0056| 0x7ffffffea638 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x00000000006ed786	419				sig = (char *) emalloc(entry.uncompressed_filesize);
gdb-peda$ p entry.uncompressed_filesize
$20 = 0x4

I create signature.bin with size is 4, after that i will step to phar_verify_signature and you will see param is passed to phar_verify_signature.

[----------------------------------registers-----------------------------------]
RAX: 0x7fffffffafa0 --> 0x0
RBX: 0x10
RCX: 0x7ffff3e710a8 --> 0x4
RDX: 0x10
RSI: 0x0
RDI: 0x7ffff3e5fb40 --> 0x12bf720 --> 0x8d6fc6 (<php_stdiop_write>:	push   rbp)
RBP: 0x7ffffffea5d0 --> 0x7fffffffa870 --> 0x7fffffffadb0 --> 0x7fffffffae50 --> 0x7fffffffaec0 --> 0x7fffffffaf50 --> 0x7fffffffb040 --> 0x7fffffffb090 --> 0x7fffffffb0c0 --> 0x7fffffffb100 --> 0x7fffffffb210 --> 0x7fffffffd510 --> 0x7fffffffe890 --> 0x7fffffffe9e0 --> 0xa1a0a0 (<__libc_csu_init>:	push   r15)
RSP: 0x7ffffffea000 --> 0x7fffffffafa0 --> 0x0
RIP: 0x6e3c77 (<phar_verify_signature+85>:	mov    rax,QWORD PTR fs:0x28)
R8 : 0xfffffffc
R9 : 0x7ffff3e70088 ("/vagrant_extend/audit/phars/signature.zip")
R10: 0x4
R11: 0x246
R12: 0x7ffff3e710a8 --> 0x4
R13: 0x7ffff3e79120 --> 0x0
R14: 0x7ffff3e79118 --> 0x0
R15: 0xfffffffc
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x6e3c65 <phar_verify_signature+67>:	mov    QWORD PTR [rbp-0x5c8],rax
   0x6e3c6c <phar_verify_signature+74>:	mov    rax,QWORD PTR [rbp+0x20]
   0x6e3c70 <phar_verify_signature+78>:	mov    QWORD PTR [rbp-0x5d0],rax
=> 0x6e3c77 <phar_verify_signature+85>:	mov    rax,QWORD PTR fs:0x28
   0x6e3c80 <phar_verify_signature+94>:	mov    QWORD PTR [rbp-0x8],rax
   0x6e3c84 <phar_verify_signature+98>:	xor    eax,eax
   0x6e3c86 <phar_verify_signature+100>:	mov    rax,QWORD PTR [rbp-0x598]
   0x6e3c8d <phar_verify_signature+107>:	mov    edx,0x0
[------------------------------------stack-------------------------------------]
0000| 0x7ffffffea000 --> 0x7fffffffafa0 --> 0x0
0008| 0x7ffffffea008 --> 0x7ffff3e79118 --> 0x0
0016| 0x7ffffffea010 --> 0x7ffff3e79120 --> 0x0
0024| 0x7ffffffea018 --> 0x7ffff3e70088 ("/vagrant_extend/audit/phars/signature.zip")
0032| 0x7ffffffea020 --> 0x7ffff3e710a8 --> 0x4
0040| 0x7ffffffea028 --> 0x10fffffffc
0048| 0x7ffffffea030 --> 0x0
0056| 0x7ffffffea038 --> 0x7ffff3e5fb40 --> 0x12bf720 --> 0x8d6fc6 (<php_stdiop_write>:	push   rbp)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 11, phar_verify_signature (fp=0x7ffff3e5fb40, end_of_phar=0x0,
    sig_type=0x10, sig=0x7ffff3e710a8 "\004", sig_len=0xfffffffc,
    fname=0x7ffff3e70088 "/vagrant_extend/audit/phars/signature.zip",
    signature=0x7ffff3e79120, signature_len=0x7ffff3e79118, error=0x7fffffffafa0)
    at /home/vagrant/Sources_Ext/audit/src/php7.0-7.0.8/ext/phar/util.c:1484
1484	{

As you can see both value sig and sig_len may lead to heap out of bound

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-09-05 05:11 UTC] stas@php.net
-Assigned To: +Assigned To: stas
 [2016-09-05 05:11 UTC] stas@php.net
The fix is in security repo as 19484ab77466f99c78fc0e677f7e03da0584d6a2 and in https://gist.github.com/e091b2255c6d071e7be49828a5e39944

please verify
 [2016-09-05 06:50 UTC] nguyenvuhoang199321 at gmail dot com
well this bug is fixed
 [2016-09-06 00:11 UTC] stas@php.net
-CVE-ID: +CVE-ID: needed
 [2016-09-12 07:48 UTC] stas@php.net
-PHP Version: 7.0Git-2016-08-23 (Git) +PHP Version: 5.6.25
 [2016-09-13 04:04 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=223266e4e46b9188353db93771369078c2e94353
Log: Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile
 [2016-09-13 04:04 UTC] stas@php.net
-Status: Assigned +Status: Closed
 [2016-09-13 04:06 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=0bfb970f43acd1e81d11be1154805f86655f15d5
Log: Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile
 [2016-09-13 04:09 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=0bfb970f43acd1e81d11be1154805f86655f15d5
Log: Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile
 [2016-09-13 04:11 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=0bfb970f43acd1e81d11be1154805f86655f15d5
Log: Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile
 [2016-09-13 09:02 UTC] ab@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=223266e4e46b9188353db93771369078c2e94353
Log: Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile
 [2016-09-15 09:30 UTC] tyrael@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=dd69327ad783ea93f1e0a9e358974c7b098f29cc
Log: Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile
 [2016-09-16 13:39 UTC] kaplan@php.net
-CVE-ID: needed +CVE-ID: 2016-7414
 [2016-10-17 10:08 UTC] bwoebi@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=223266e4e46b9188353db93771369078c2e94353
Log: Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile
 [2016-10-17 10:08 UTC] bwoebi@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=0bfb970f43acd1e81d11be1154805f86655f15d5
Log: Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 15:01:30 2024 UTC