Null Pointer Dereference on including PHAR file twice resulted in Segmentation-fault

Hey, I am SpyD3r(@TarunkantG) and in this blog, I will be discussing the bug(the Segmentation-fault) I have found in php while playing with phar, couldn’t make this bug a security issue though :(. The issue was occurring when the same phar file gets included twice and this bug was affected in all versions of PHP.

Description:

When I tried to import a “phar” file (i.e using the phar wrapper) twice, php results in a segmentation fault. Attaching gdb, I 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.
Basically, Null pointer dereference is taking place in the _php_stream_seek because the php_stream that the _php_stream_seek function is trying to access was closed afer the first include.

Impact:

This could be dangerous, as Local File Inclusion(LFI) + Segmentation_fault will leads to RCE, as I disussed this in my previous blog, check it here. 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.

But getting all this(File Upload vuln + Partial PHP code execution(we need this because we need to include phar file twice)) on one application in real-world is somewhat tough, so this bug is open now.

Test-Script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
For creating phar file
<?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");
?>

Practical aspect

Here is practical aspect of this, if you use this big php code base, it is easily possible that you created a file and includes two of other files and a chance there both of the other file includes same file. We see an example here.
Let’s say a.php contains:

1
2
3
4
5
6
<?php
#which includes b.php and c.php
include("b.php");
include("c.php");
echo "hey";
?>

b.php includes test.phar:

1
2
3
4
<?php
include("phar://test.phar");
echo "hello";
?>

c.php also includes test.phar:

1
2
3
4
<?php
include("phar://test.phar");
echo "bye";
?>

And on running a.php
Expected result is: hellobyehey
Actual result is: hello [1] Segmentation fault

Screen-shots

image
image
image
image
image

The bug was reported in bugs.php.net, you can see all the comments and description there, follow the following link: https://bugs.php.net/bug.php?id=77432

I hope you find this blog worth to read.