PHP反序列化初探

PHP反序列化初探

php序列化是什么?

在反序列化之前,先来看看php序列化是什么样的,php序列化和反序列化由serialize()和unserialize()这两个函数进行相互转化的,简单的说就是serialize()将一串字符串、数组、对象进行格式化处理,然后再有unserialize()函数将格式化处理后的字符串、数组进行还原;
代码:

<?php
	$str = "this is php";
	$arr = array("username"=>"xiaoming","password"=>"!@#123");

	
	class DemoSer{
		public $name = "xiaoming";
		public $sex = "man";
		public $age = "14";
	}
	
	
	echo "string-".serialize($str)."</br>";
	echo "array-".serialize($arr)."</br>";
	
	
	$example = new DemoSer();
	$example->name = "CC";
	$example->sex = "woman";
	$example->age = "12";
	
	echo serialize($example);
	echo "</br>";
	$flag = serialize($example);
	$unser = unserialize($flag);

?>

file

这样看着序列化之后的格式肯定不是人看的;所以对DemoSer序列化后的格式进行注释一下,标准格式如下:

O:7:"DemoSer":3:{s:4:"name";s:2:"CC";s:3:"sex";s:5:"woman";s:3:"age";s:2:"12";}

O:7: 这是一个object对象,长度为7
“DemoSer”:3: 代表名字为DemoSer,DemoSer有三个属性
{
s:4:“name”; string类型,属性名长度为4,属性名是name
s:2:“CC”; string类型,参数值长度2,参数值是CC
s:3:“sex”; string类型,属性名长度为3,属性名是sex
s:5:“woman”; string类型,参数值长度5,参数值是woman
s:3:“age”; string类型,属性名长度为3,属性名是age
s:2:“12”; string类型,参数值长度2,参数值是12
}

php反序列化

接下来使用unserialize()将序列化后的对象还原,代码:

<?php
	$str = "this is php";
	$arr = array("username"=>"xiaoming","password"=>"!@#123");

	class DemoSer{
		public $name = "xiaoming";
		public $sex = "man";
		public $age = "14";
	}
	
	$flag1 = serialize($str);
	echo "string-".unserialize($flag1)."</br>";
	$flag2 = serialize($arr);
	print_r(unserialize($flag2))."</br>";
	
	echo "</br>";
	$example = new DemoSer();
	$example->name = "CC";
	$example->sex = "woman";
	$example->age = "12";
	$flag3 = serialize($example);
	print_r(unserialize($flag3));

?>

file

为什么出现反序列化漏洞

现在来看为什么这里反序列化会出现漏洞呢?主要是反序列化传递的参数可控,如果反序列化对象中存在魔术方法,而且魔术方法中的代码有能够被我们控制,漏洞就这样产生了,根据不同的代码可以导致各种攻击;php中的魔术方法在函数前会有"__",;这些魔术方法在类的创建或结束的时候会默认执行某些函数:__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString();比如下面的代码:

<?php 
	class TestDemo{
		public $username = "admin";
		public $password = "passwd";
		public function out(){
			echo "username:".$this->username.";password:".$this->password."</br>";
		}
		
		public function __destruct(){
			
			echo "__destruct()"."</br>";
		}
		
		public function __construct(){
			echo "__construct()"."</br>";
		}
		
		public function __sleep(){
			echo "__sleep()"."</br>";
			return  array("username","password");
		}
		
		public function __wakeup(){
			echo "__wakeup()"."</br>";
		}
		
		public function __toString(){
			return "__toString()"."</br>";
			
		}
	}
	#创建对象调用_construct()
	$NewObject = new TestDemo();
	$NewObject->username = "xiaoming";
	$NewObject->password = "!@#123";
	#序列化对象调用__sleep()
	$flag = serialize($NewObject);
	#输出序列化后的字符串
	print 'serialize:'.$flag."</br>";
	#重建对象调用__wakeup()
	$NewObject2 = unserialize($flag);
	echo "unserialize:".$NewObject2."</br>";
	#调用out()输出数据
	$NewObject2->out();
	#脚本结束调用__destruct

?>

file

现在我们来执行一下反序列化会产生的漏洞:

<?php
	class Demo{
		var $name = "xiaoming";
		function __destruct(){
			@eval($this->name);#在这里执行了phpinfo()函数;
		}
	}
	$name = $_POST['name'];
	$len = strlen($name)+1;
	$str = "O:4:\"Demo\":1:{s:4:\"name\";s:".$len.":\"".$name.";\";}";
	$test__unser = unserialize($str);
	
?>

执行效果:
file

从代码中可以知道phpinfo()函数实在程序结束时调用了__destruct()中执行了,同时里面还有@eval()函数,由此可以设想,直接在__destruct()函数中执行phpinfo()会怎么样?:
file

<?php
	class Demo{
		var $name = "xiaoming";
		function __destruct(){
			echo "hello";
			@eval(phpinfo());
			
		}
	}
	$name = $_POST['name'];
	$len = strlen($name)+1;
	$str = "O:4:\"Demo\":1:{s:4:\"name\";s:".$len.":\"".$name.";\";}";
	$test__unser = unserialize($str);
	
?>

执行效果
file
直接在__destruct()中执行phpinfo():
file

在上面的代码中有@eval函数,也可以正常解析phpinfo(),这里还可以使用菜刀连接成为webshell,
file

file

最后基本知道php反序列化漏洞是怎么产生了~~
写的东西很基础,大佬勿喷啦……
这篇文章我先发布在圈子里面,过了一段时间后我再发布到自己的博客中……

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值