WEB攻防-PHP特性-metinfoCMS审计实例

前置知识:PHP函数缺陷

测试环境:MetInfo CMS

  1. 函数缺陷导致的任意文件读取

漏洞URL:/include/thumb.php?dir=

漏洞文件位置:MetInfo6.0.0\app\system\include\module\old_thumb.class.php

<?php


defined('IN_MET') or exit('No permission');

load::sys_class('web');

class old_thumb extends web{

      public function doshow(){
        global $_M;

         $dir = str_replace(array('../','./'), '', $_GET['dir']);
         echo $dir;
         echo "<br/>";
          echo !(substr(str_replace($_M['url']['site'], '', $dir),0,4) == 'http');
          echo "<br/>";

        if(substr(str_replace($_M['url']['site'], '', $dir),0,4) == 'http' && strpos($dir, './') === false){
            
            header("Content-type: image/jpeg");
            echo $dir;
            echo 11111111;
            ob_start();
            readfile($dir);
            
            ob_flush();
            flush();
            die;
        }

        if($_M['form']['pageset']){
          $path = $dir."&met-table={$_M['form']['met-table']}&met-field={$_M['form']['met-field']}";

        }else{
          $path = $dir;
        }
        $image =  thumb($path,$_M['form']['x'],$_M['form']['y']);
        if($_M['form']['pageset']){
          $img = explode('?', $image);
          $img = $img[0];
        }else{
          $img = $image;
        }
        if($img){
            header("Content-type: image/jpeg");
            ob_start();
            readfile(PATH_WEB.str_replace($_M['url']['site'], '', $img));
            echo PATH_WEB.str_replace($_M['url']['site'], '', $img);
            echo 2222222;
            ob_flush();
            flush();
        }

    }
}


?>

源码中,      $dir = str_replace(array('../','./'), '', $_GET['dir']);过滤了../和./,但str_replace是不迭代循环过滤的,可以双写绕过的

可以看到代码中 if(substr(str_replace($_M['url']['site'], '', $dir),0,4) == 'http' && strpos($dir, './') === false)这个条件用于检测一个路径$dir是否是一个以'http'开头且不是相对于当前目录的(不包含'./')。但是,这样的判断方式并不完全准确,因为它只是检查了前4个字符是否为'http',而没有确保整个字符串是一个有效的URL。同时,检查'./'来排除相对路径的方式也是有限的,因为它没有考虑如'../'或其他相对路径形式。当我们试图构造playload:http://localhost/MetInfo/include/thumb.php?dir=http\.....//\config\config_db.php

readfile($dir);打开http\.....//\config\config_db.php这个路径是一个无效路径,所以继续看代码

if($_M['form']['pageset'])

在全局搜索pageset看到是一个跳转地址加参数pageset=1

而我们构造playload没有跳转动作,所以应该是不会满足条件的,也就是说构造的dir会直接赋值给$path

再看下一行 $image =  thumb($path,$_M['form']['x'],$_M['form']['y']);这里对path作了处理,应该是宽高处理,追踪thumb这个函数

找到最后返回调用的函数met_thumb

可以看到红框上面的又做了一次../和./的过滤,如果没有http会执行红框下面的代码,在$image = $this->get_thumb();追踪到get_thumb可以看到return file_exists($thumb_path) ? $this->thumb_url : $this->create_thumb();,继续追踪 $this->create_thumb();,可以看到会返回一个默认路径

完整代码

<?php

defined('IN_MET') or exit('No permission');



class image{

	/**
	 * 图片信息
	 * @var [type]
	 */
	public $image;

	/**
	 * 域名
	 * @var [type]
	 */
	public $host;

	/**
	 * 请求图片宽
	 * @var int
	 */
	public $x;

	/**
	 * 请求图片高
	 * @var int
	 */
	public $y;

	/**
	 * 生成图片宽
	 * @var [type]
	 */
	public $thumb_x;

	/**
	 * 生成图片高
	 * @var [type]
	 */
	public $thumb_y;

	/**
	 * 缩略图存放目录
	 * @var [type]
	 */
	public $thumb_dir;

	/**
	 * 缩略图路径
	 * @var [type]
	 */

	/**
	 * 缩略图url
	 * @var [type]
	 */
	public $thumb_url;

	public $thumb_path;


	public function met_thumb($image_path, $x = '', $y = ''){

		global $_M;
		if(!isset($image_path)){
			$image_path = $_M['url']['site'].'public/images/metinfo.gif';
		}
		$this->image_path = str_replace(array($_M['url']['site'],'../','./'), '', $image_path);
		// 如果地址为空 返回默认图片
		if(!$this->image_path){
			return $_M['url']['site'].'public/images/metinfo.gif';
		}
		// 如果去掉网址还有http就是外部链接图片 不需要缩略处理
		if(strstr($this->image_path, 'http')){
			return $this->image_path;
		}
		$this->x = is_numeric($x) ? intval($x) : false;
		$this->y = is_numeric($y) ? intval($y) : false;

		$this->image = pathinfo($this->image_path);
		$this->thumb_dir = PATH_WEB.'upload/thumb_src/';
		$this->thumb_path = $this->get_thumb_file() . $this->image['basename'];

		$image = $this->get_thumb();
		return $image;
	}


	public function get_thumb_file() {
		global $_M;
		$x = $this->x;
		$y = $this->y;

		if($path = explode('?', $this->image_path)){
			$image_path = $path[0];
		}else{
			$image_path = $this->image_path;
		}

		$s = file_get_contents(PATH_WEB.$image_path);

		$image = imagecreatefromstring($s);

		$width = imagesx($image);//获取原图片的宽
		$height = imagesy($image);//获取原图片的高
		if($x && $y) {
			$dirname = "{$x}_{$y}/";
			$this->thumb_x  = $x;
			$this->thumb_y  = $y;
		}

		if($x && !$y) {
			$dirname 		= "x_{$x}/";
			$this->thumb_x  = $x;
			$this->thumb_y  = $x / $width * $height;
		}

		if(!$x && $y) {
			$dirname 		= "y_{$y}/";
			$this->thumb_y  = $y;
			$this->thumb_x  = $y / $height * $width;
		}

		$this->thumb_url = $_M['url']['site'] . 'upload/thumb_src/' . $dirname . $this->image['basename'];

		$dirname = $this->thumb_dir . $dirname ;

		if(stristr(PHP_OS,"WIN")) {
			$dirname = @iconv("utf-8","GBK",$dirname);
		}

		return $dirname;
	}

	public function get_thumb() {
		if($path = explode('?', $this->thumb_path)){
			$thumb_path = $path[0];
		}else{
			$thumb_path = $this->thumb_path;
		}

		return file_exists($thumb_path) ? $this->thumb_url : $this->create_thumb();
	}

	public function create_thumb() {

		global $_M;
		$thumb = load::sys_class('thumb','new');
		$thumb->set('thumb_save_type',3);
		$thumb->set('thumb_kind',$_M['config']['thumb_kind']);
		$thumb->set('thumb_savepath',$this->get_thumb_file());
		$thumb->set('thumb_width',$this->thumb_x);
		$thumb->set('thumb_height',$this->thumb_y);
		$suf = '';
		if($path = explode('?', $this->image_path)){
			$image_path = $path[0];
			$suf .= '?'.$path[1];
		}else{
			$image_path = $this->image_path;
		}

		if($_M['config']['met_big_wate'] && strpos($image_path, 'watermark')!==false){
			$image_path = str_replace('watermark/', '', $image_path);
		}
		$image = $thumb->createthumb($image_path);
		if($_M['config']['met_thumb_wate'] && strpos($image_path, 'watermark')===false){
			$mark = load::sys_class('watermark','new');
			$mark->set('water_savepath',$this->get_thumb_file());
			$mark->set_system_thumb();
			$mark->create($image['path']);
		}


		if($image['error']){
            if (!$_M['config']['met_agents_switch']) {
                return $_M['url']['site'].'public/images/metinfo.gif'.$suf;
            }else{
                $met_agents_img =str_replace('../', '', $_M['config']['met_agents_img']);
                $image_path = $_M['url']['site'] . $met_agents_img;
                return $_M['url']['site'].$met_agents_img.$suf;
            }
		}

		return $_M['url']['site'].$image['path'].$suf;
	}


}

重点看红框部分,再贴一次上面的图

只要二次过滤后的路径有http就返回二次过滤的路径

回到漏洞页面代码,也就是$image接收thump处理后的一个二次过滤../和./的路径,

下面又if($_M['form']['pageset']),这里又直接执行else赋值给$img

最后一个判断可以看到 readfile(PATH_WEB.str_replace($_M['url']['site'], '', $img));

PATH_WEB是一个常量,包含了指定的路径

拼接我们传进来的值,而这个值会被二次过滤../和./,也就是说,我们需要构造一个绕过二次过滤的playload就可以任意读取已知路径的文件

/MetInfo/include/thumb.php?dir=ahttp\.....//\config\config_db.php

 注意:

  • http前面可以加任何字符来绕过if(substr(str_replace($_M['url']['site'], '', $dir),0,4) == 'http' && strpos($dir, './') === false),但不能加后面,加前面就满足了substr(str_replace($_M['url']['site'], '', $dir),0,4)的条件
  • 第一个反斜杠也可以是/,只是为了闭合ahppt这个文件名,
  • 而第二个加了底纹的\不可以时候/,因为会被二次过滤,过滤后会变成ahttp\config\config_db.php,而\过滤之后是ahttp\..\config\config_db.php,才能使..\返回上一节目录
  • .. 的作用与之前的目录是否存在无关,它总是表示向上移动一个目录级别。而路径解析器会忽略任何不存在的目录部分,并继续处理剩余的有效部分。这就是为什么 ahttp\..\ 会返回到 MetInfo 这个目录,即使 ahttp\ 目录不存在。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Blender曲线操作

1.几种常见建模方式 -多边形建模&#xff1a;Blender&#xff0c;C4D&#xff0c;3DsMax&#xff0c;MaYa -曲线&#xff1a; -曲面&#xff1a;Rhino&#xff08;Nurbs&#xff09; -雕刻&#xff1a;Blender&#xff0c;ZBrush -蜡笔&#xff1a;Blender 1&#xff09;新…

【Linux】dlopen: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29‘ not found

[30116] Error loading Python lib /tmp/_MEIlvdUu6/libpython3.8.so.1.0: dlopen: /lib/x86_64-linux-gnu/libm.so.6: version GLIBC_2.29 not found (required by /tmp/_MEIlvdUu6/libpython3.8.so.1.0)1 cd到指定路径 cd /usr/local 2 下载 wget http://ftp.gnu.org/gnu/gl…

电影交流|基于SprinBoot+vue的电影交流平台小程序系统(源码+数据库+文档)

电影交流平台目录 目录 基于SprinBootvue的电影交流平台小程序系统 一、前言 二、系统设计 三、系统功能设计 1用户信息管理 2 电影信息管理 3公告信息管理 4论坛信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取…

Python自学篇3-PyCharm开发工具下载、安装及应用

一、Python开发工具 自学篇1中讲到了安装Python之后出现的几个应用程序&#xff0c;其中IDLE、Python.exe都可以用来编写python程序&#xff0c;也可以进行调试&#xff1b;但是比较基础&#xff0c;比较原始&#xff0c;调试不方便&#xff0c;界面也不友好&#xff0c;需要更…

Apache Seata AT 模式事务隔离级别与全局锁设计

title: 详解 Seata AT 模式事务隔离级别与全局锁设计 author: 张乘辉 keywords: [Seata、分布式事务、AT模式、Transaction、GlobalLock] description: Seata AT 模式的事务隔离是建立在支事务的本地隔离级别基础之上的&#xff0c;在数据库本地隔离级别读已提交或以上的前提下…

八_实验1:创建 VLAN 和划分端口

1、实验目的 通过本实验可以掌握&#xff1a; VLAN的概念。创建VLAN的方法。把交换机端口划分到VLAN中的方法。 2、实验​​​​​​拓扑 创建 VLAN 和划分端口的实验拓扑如下图所示。 图8-5 创建 VLAN 和划分端口的实验拓扑 3、实验步骤 &#xff08;1&#xff09;实验准…

力扣-有效的数独

请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 &#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考示例图&#xff09; 注…

AI图书推荐:基于AI的商业数据分析应用

《基于AI的商业数据分析应用》&#xff08;AI-Based Data Analytics: Applications for Business Management&#xff09;的作者是Kiran Chaudhary、 Mansaf Alam。 本书涵盖了与营销和商业分析相关的各种主题。它探讨了组织如何通过使用数据分析及时做出更好的决策来增加利润。…

verilog分析task的接口设计,证明这种写法:assign {a,b,c,d} = links;

verilog分析task的接口设计&#xff0c;证明这种写法&#xff1a;assign {a,b,c,d} links; 1&#xff0c;task在状态机中的使用好处&#xff1a;2&#xff0c;RTL设计3&#xff0c;测试testbench4&#xff0c;波形分析&#xff0c;正确&#xff01; 参考文献&#xff1a; 1&am…

蓝牙核心规范(core Specification)与应用规范(Profile)

加zkhengyang可申请加入蓝牙音频研究开发交流答疑群(课题组)&#xff0c;赠送实际蓝牙耳机项目核心开发资料&#xff0c; 我们看到的大部分资料对于蓝牙协议分层一般是核心规范。 射频&#xff0c;基带&#xff0c;链路管理属于蓝牙硬件模块(一般由硬件实现比如FPGA) 逻辑链…

MongoDB数据库迁移的两种办法

在做系统运维时&#xff0c;经常需要对数据库进行迁移&#xff0c;今天这里分享一下MongoDB数据库数据迁移的办法。两种方法 方法1 利用NoSQLBooster for MongoDB直接复制粘贴 这种方法&#xff0c;适合在windows电脑上&#xff0c;可以直接访问原始和目标两个MongoDB库的。优…

Burp自定义插件实现请求拦截

在安全测试时&#xff0c;经常需要对请求进行拦截以及配置管理&#xff0c;以便过滤域名或路径的请求。例如&#xff1a;被测对象会不断收集信息&#xff08;例如IP地址、设备信息&#xff09;通过HTTP传给服务端。本文将介绍如何使用Burp Suite的扩展插件&#xff0c;通过开发…

释放Stable Diffusion 无限可能

最近在整理大语言模型的系列内容&#xff0c;Stable Diffusion 是我下一篇博客的主题。关注 Stable Diffusion&#xff0c;是因为它是目前最受欢迎和影响力最大的多模态生成模型之一。Stable Diffusion 于 2022 年 8 月发布&#xff0c;主要用于根据文本的描述产生详细图像&…

微服务使用SockJs+Stomp实现Websocket 前后端实例 | Vuex形式断开重连、跨域等等问题踩坑(二)

大家好&#xff0c;我是程序员大猩猩。 上次我们实践了&#xff0c;Java后端如何完成SockJSStomp的配置实现。 微服务使用SockJsStomp实现Websocket 前后端实例 | Vuex形式断开重连、跨域等等问题踩坑&#xff08;一&#xff09; 那么今天我们做一下web vue端的是如何来实现…

android studio拍照功能问题解决

1.点击拍照功能直接闪退 2.拍照后不能选择确认键&#xff0c;无法保存 上述是在android studio做项目中经常会使用到模拟器或真机的拍照功能时主要遇到的两个问题。 解决方法&#xff1a; 1.直接闪退问题&#xff1a; if(Build.VERSION.SDK_INT>Build.VERSION_CODES.N)…

谈谈进些年的BLE开发项目

加zkhengyang可申请加入蓝牙音频研究开发交流答疑群(课题组) 最早接触BLE项目是在做一款女性按摩器产品上&#xff0c;所谓的生活用品&#xff0c;用的是TI CC2640&#xff0c;资料齐全&#xff0c;上手快&#xff0c;配合手机app通讯开发&#xff0c;当然这个是单模的蓝牙芯…

学习C语言的指针

有一阵没更新了&#xff0c;因为最近比较繁忙&#xff0c;所以更新比较慢&#xff0c;还在慢慢学习 话不多说&#xff0c;开始今天的内容&#xff0c;聊一聊C语言指针。 很多小伙伴可能会被指针这个名字吓到&#xff0c;觉得很难&#xff0c;实际上确实有点难&#xff0c;但是…

cesium教程

环境搭建 vscode安装Visual Studio Code - Code Editing. Redefined nodejs安装Node.js — Run JavaScript Everywhere cesium源码下载编译 cesium官网下载源码https://cesium.com/downloads/ 解压下载的源码 VsCode打开远吗&#xff0c;找到index.html,右键打开 Open wit…

职场人是如何被拉开差距的?

事实上&#xff0c;职场人的差距从第一天就拉开了。 心理学里有一个词&#xff0c;叫做“首因效应&#xff0c;说的是人们在第一次接触时形成的印象&#xff0c;将会决定后续认知的基调。 入职第一天&#xff0c;从自我介绍开始&#xff0c;展示自己的特长&#xff0c;给大家…

unity项目《样板间展示》开发:菜单界面

unity项目《样板间展示》开发&#xff1a;菜单界面 前言UI菜单创建逻辑实现结语 前言 这是这个项目demo教程的最后一节&#xff0c;这节是菜单界面部分的创建 UI菜单创建 创建一个新的场景&#xff0c;在Scene文件中右键选择Create->Scene&#xff0c;创建新的场景 在场景…