Sec Bug->Bug #77432 [Opn->Ver]: Segmentation fault when including the same phar file twice
| From: | stas@php.net | Date: | Mon, 21 Jan 2019 01:56:58 +0000 |
| Subject: | Sec Bug->Bug #77432 [Opn->Ver]: Segmentation fault when including the same phar file twice | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-219100@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=77432&edit=1
ID: 77432
Updated by: stas@php.net
Reported by: tarunkant05 at gmail dot com
Summary: Segmentation fault when including the same phar file
twice
-Status: Open
+Status: Verified
-Type: Security
+Type: Bug
Package: PHAR related
Operating System: Linux
PHP Version: Irrelevant
Block user comment: N
Private report: Y
New Comment:
The problem seems to be occurring because first include closes phar's file stream, but the
structure remains in phar_fname_map cache, and is loaded on the second open, but the closed FP is
not reopened. Not sure what would be the proper fix though, need someone who knows phar better.
Previous Comments:
------------------------------------------------------------------------
[2019-01-12 18:24:47] tarunkant05 at gmail dot com
Changed the Summary to the exact point because of that it is happening.
------------------------------------------------------------------------
[2019-01-11 17:04:30] tarunkant05 at gmail dot com
Basically, Null pointer dereference is taking place in the
_php_stream_seek. I think
this happens because the php_stream that the _php_stream_seek function is trying to
access was closed afer the first include.
------------------------------------------------------------------------
[2019-01-10 11:45:15] tarunkant05 at gmail dot com
We can also take a new view that how this bug can be dangerous:
It's normal that we include files, and that file also could include other files, so here is the
practical view of it:
a.php:
<?php
#which includes b.php and c.php
include("b.php");
include("c.php");
echo "hey";
?>
b.php: It includes test.phar
<?php
include("phar://test.phar");
echo "hello";
?>
c.php: It also includes test.phar
<?php
include("phar://test.phar");
echo "bye";
?>
On running php a.php
Expected Result: hellobyehey
Actual Result: hello [1] Segmentation fault
------------------------------------------------------------------------
[2019-01-09 13:05:44] tarunkant05 at gmail dot com
Description:
------------
* Version no of PHP - I tried it out on version 7.0.32, 7.1.25, 7.2.13, 7.3.0
* Description - When we try to import a "phar" file (i.e using the phar wrapper) twice,
php results in a segmentation fault. Attaching gdb, we noticed that the crash occurred in the
_php_stream_seek function. The issue was that all the arguments to this function were
null (including the php_stream object). This leads to an invalid compare statement (accessing an
invalid address), resulting in a crash. We tried analyzing this, but since we are novices with the
php codebase, all the following could be wrong. phar_stream_read called
_php_stream_seek. The argument of phar_stream_read which is a php_stream
had the stream->abstract->fp as NULL, instead of a valid php_stream.
* Configure line - ./configure --enable-debug
* Impact - This could be dangerous, as LFI + Segmentation_fault will lead to RCE. This can be
exploited as sending php shell, at the time it gets segmentation fault will lead to make temporary
php file in temp folder(which won't get deleted) and can be triggered using LFI with
brute-forcing for file.
* Regarding the patch: Since we did not exactly understand the occurrence of this bug, we are afraid
that we cannot provide a patch file.
Test script:
---------------
1st you need to make a phar file, you can use this php code to make the same:
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); ? >');
$phar->stopBuffering();
?>
Script that triggers Segmentation fault:
<?php
include("phar://test.phar");
include("phar://test.phar");
?>
Expected result:
----------------
Usually it should include same file twice, without any failure.
Actual result:
--------------
Segmentation fault, here is the Backtrace:
gdb-peda$ bt
#0 0x0000000000812dca in _php_stream_seek (stream=0x0, offset=0x0, whence=0x0) at
/home/vignesh/Documents/Tarun/pseudo/php-7.0.33/main/streams/streams.c:1268
#1 0x000000000069b3b8 in phar_stream_read (stream=0x7f3be8c5f900, buf=0x7f3be8c7d000 "<?php
__HALT_COMPILER(); ?>\r\n\240\002", count=0x2000)
at /home/vignesh/Documents/Tarun/pseudo/php-7.0.33/ext/phar/stream.c:380
#2 0x00000000008119f9 in _php_stream_fill_read_buffer (stream=0x7f3be8c5f900, size=0x1000)
at /home/vignesh/Documents/Tarun/pseudo/php-7.0.33/main/streams/streams.c:675
#3 0x0000000000811ba3 in _php_stream_read (stream=0x7f3be8c5f900, buf=0x7f3be8c83000 "<?php
__HALT_COMPILER(); ?>\r\n", size=0x1000)
at /home/vignesh/Documents/Tarun/pseudo/php-7.0.33/main/streams/streams.c:722
#4 0x00000000008b230f in zend_stream_read (file_handle=0x7ffcae905130, buf=0x7f3be8c83000
"<?php __HALT_COMPILER(); ?>\r\n", len=0x1000)
at /home/vignesh/Documents/Tarun/pseudo/php-7.0.33/Zend/zend_stream.c:177
#5 0x00000000008b2727 in zend_stream_fixup (file_handle=0x7ffcae905130, buf=0x7ffcae904d78,
len=0x7ffcae904d80)
at /home/vignesh/Documents/Tarun/pseudo/php-7.0.33/Zend/zend_stream.c:261
#6 0x000000000082df93 in open_file_for_scanning (file_handle=0x7ffcae905130) at
Zend/zend_language_scanner.l:508
#7 0x000000000082e326 in compile_file (file_handle=0x7ffcae905130, type=0x2) at
Zend/zend_language_scanner.l:578
#8 0x00000000006b1f27 in phar_compile_file (file_handle=0x7ffcae905130, type=0x2) at
/home/vignesh/Documents/Tarun/pseudo/php-7.0.33/ext/phar/phar.c:3349
#9 0x000000000082e6c8 in compile_filename (type=0x2, filename=0x7f3be8c78240) at
Zend/zend_language_scanner.l:649
#10 0x00000000008f2c0f in ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER () at
/home/vignesh/Documents/Tarun/pseudo/php-7.0.33/Zend/zend_vm_execute.h:3659
#11 0x00000000008ea708 in execute_ex (ex=0x7f3be8c14030) at
/home/vignesh/Documents/Tarun/pseudo/php-7.0.33/Zend/zend_vm_execute.h:414
#12 0x00000000008ea819 in zend_execute (op_array=0x7f3be8c86000, return_value=0x0) at
/home/vignesh/Documents/Tarun/pseudo/php-7.0.33/Zend/zend_vm_execute.h:458
#13 0x000000000088aed4 in zend_execute_scripts (type=0x8, retval=0x0, file_count=0x3) at
/home/vignesh/Documents/Tarun/pseudo/php-7.0.33/Zend/zend.c:1445
#14 0x00000000007f2be6 in php_execute_script (primary_file=0x7ffcae907950) at
/home/vignesh/Documents/Tarun/pseudo/php-7.0.33/main/main.c:2516
#15 0x0000000000953fa8 in do_cli (argc=0x2, argv=0x1724290) at
/home/vignesh/Documents/Tarun/pseudo/php-7.0.33/sapi/cli/php_cli.c:977
#16 0x0000000000955176 in main (argc=0x2, argv=0x1724290) at
/home/vignesh/Documents/Tarun/pseudo/php-7.0.33/sapi/cli/php_cli.c:1347
#17 0x00007f3beb835830 in __libc_start_main (main=0x95496b <main>, argc=0x2,
argv=0x7ffcae908cd8, init=<optimized out>, fini=<optimized out>,
rtld_fini=<optimized out>, stack_end=0x7ffcae908cc8) at ../csu/libc-start.c:291
#18 0x0000000000422449 in _start ()
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=77432&edit=1