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

news2024/10/5 18:34:38

前置知识: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\ 目录不存在。

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

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

相关文章

ElasticSearch语句中must,must_not,should 组合关系

前言&#xff1a; 在实际应用中&#xff0c;发现当bool中同时使用must和should 没有达到想要的想过&#xff0c;而是只展示了must中的命中数据&#xff0c;所以打算探究一下bool中 三种逻辑关系的组合。 上述查询语句只展示了must的结果&#xff0c;没有should中的结果&#…

Kafka 3.x.x 入门到精通(06)Kafka进阶

Kafka 3.x.x 入门到精通&#xff08;06&#xff09;——对标尚硅谷Kafka教程 3. Kafka进阶3.1 Controller选举3.2 Broker上线下线3.3 数据偏移量定位3.4 Topic删除3.5 日志清理和压缩3.7 页缓存3.8 零拷贝3.9 顺写日志3.10 Linux集群部署3.10.1 集群规划3.10.2 安装虚拟机(略)3…

MemFire解决方案-物联网数据平台解决方案

方案背景 随着各种通讯、传感技术发展&#xff0c;数据通讯成本的急剧下降&#xff0c;数以万亿计的智能设备&#xff08;智能手环、智能电表、智能手机、各种传感器设备等&#xff09;接入网络&#xff0c;并源源不断的产生海量的实时数据。这些海量数据的价值挖掘&#xff0…

15.Blender Eevee和Cycles渲染引擎对比

初步介绍 Eevee是实时渲染的引擎&#xff0c;会省略一些解算方式&#xff0c;尤其对光线和阴影 Cycles会考虑这些因素&#xff0c;所以会对光线和阴影的表达更加真实&#xff0c;有一个实时光线追踪的功能 Cycles渲染完之后&#xff0c;每移动一次画面&#xff0c;都会重新渲染…

机器学习之Scikit-learn基础教程

Scikit-learn&#xff08;简称sklearn&#xff09;是一个广泛使用的Python机器学习库&#xff0c;它提供了各种算法和工具&#xff0c;用于数据挖掘和数据分析。本教程将介绍sklearn的基本概念和使用方法。 1. 安装Scikit-learn 如果你还没有安装scikit-learn&#xff0c;可以…

设计模式学习笔记 - 开源实战五(下):总结Mybatis中用到的10种设计模式

概述 本章再对 Mybatis 用到的设计模式做一个总结。它用到的设计模式也不少。有些前面章节已经经过了&#xff0c;有些则比较简单。 SqlSessionFactoryBuilder&#xff1a;为什么要用建造者模式来创建 SqlSessionFactory&#xff1f; 在《Mybatis如何权衡易用性、性能和灵活性…

nvm的下载与安装

nvm&#xff08;Node Version Manager&#xff09;是一个用于管理 Node.js 版本的工具&#xff0c;它允许您在同一台计算机上安装和切换不同的 Node.js 版本。 一、下载地址 https://github.com/coreybutler/nvm-windows/releases 二、安装nvm 三、设置环境变量 在命令提示…

python之List列表

1. 高级数据类型 Python中的数据类型可以分为&#xff1a;数字型&#xff08;基本数据类型&#xff09;和非数字型&#xff08;高级数据类型&#xff09; 数字型包含&#xff1a;整型int、浮点型float、布尔型bool、复数型complex 非数字型包含&#xff1a;字符串str、列表l…

URL路由基础与Django处理请求的过程分析

1. URL路由基础 对于高质量的Web应用来讲&#xff0c;使用简洁、优雅的URL设计模式非常有必要。Django框架允许设计人员自由地设计URL模式&#xff0c;而不用受到框架本身的约束。对于URL路由来讲&#xff0c;其主要实现了Web服务的入口。用户通过浏览器发送过来的任何请求&am…

张小泉签约实在智能,用实在Agent打造自动化高

在不少老杭州人的童年记忆里&#xff0c;妈妈裁剪衣服、料理食材、修剪各种物品&#xff0c;用的都是张小泉刀剪。 近日&#xff0c;实在智能与“刀剪第一股”张小泉&#xff08;股票代码&#xff1a;301055.SZ&#xff09;正式达成合作&#xff0c;实在Agent数字员工助力张小…

PT Knockin - 仅需两分钟的在线电子邮件安全检查

我们很高兴向您介绍电子邮件安全评估工具 PT Knockin。 PT Knockin 是一个基于云的 SaaS 解决方案。这意味着企业无需下载或安装任何东西。他们只需访问 PT Knockin 网页&#xff0c;输入电子邮件地址并登录&#xff0c;然后在两分钟内收到电子邮件安全有效性分析报告以及解决…

Unreal Engine添加UGameInstanceSubsystem子类

点击C类文件夹&#xff0c;在右边的区域点击鼠标右键&#xff0c;在弹出的菜单中选择“新建C类”在弹出的菜单中选中“显示所有类”&#xff0c;选择GameInstanceSubsystem作为父类, 点击“下一步”按钮输入子类名称“UVRVIUOnlineGameSubsystem”&#xff0c;选择插件作为新类…

HTTP网络协议的请求方法,具体详解(2024-04-26)

1、HTTP 即超文本传输协议&#xff0c;是一种实现客户端和服务器之间通信的响应协议&#xff0c;它是用作客户端和服务器之间的请求 根据 HTTP 标准&#xff0c;HTTP 请求可以使用多种请求方法。 2、方法分类 HTTP1.0 定义了三种请求方法&#xff1a; GET, POST 和 HEAD 方…

[Linux][网络][网络基础][协议][网络传输基本流程][数据包封装和分用]详细讲解

目录 1.认识协议1."协议"本质就是一种约定2.计算机中的协议 2.网络协议初识1.协议分层2.OSI七层模型3.TCP/IP五层(四层)模型 3.网络传输基本流程0.预备知识1.跨网络的两台主机通信2.网络通信的基本轮廓 4.数据包封装和分用1.数据封装的过程2.数据分用的过程3.总结 5.…

杰发科技AC7840——ADC简介(1)_双路ADC同时使用

0. 简介 1. 特性 2. 双路ADC Sample里面没有双路的&#xff0c;以为那个规则组只有一个通道&#xff0c;看了外设寄存器才发现&#xff0c;原来他的通道是双路的。 注意1: ADC硬件引脚的配置 注意2: 规则组长度设置和 RSEQ序列号和CH通道号组合应该就对应了转换顺序&#xff0…

玩转手机在AidLux上安装宝塔面板

AidLux&#xff0c;手机不用刷机、不用root&#xff0c;直接在手机应用市场就能下载使用。 1.4G的应用包&#xff0c;看起来挺大的&#xff0c;那是因为内嵌了一套完整的AIoT应用开发和部署平台。 不仅Android手机可以玩&#xff0c;华为的Harmony系统也可以使用。 使用它最主…

认识HTTP

HTTP缺点 通信使用明文&#xff08;不加密&#xff09;&#xff0c;内容可能会被窃听 不验证通信方的身份&#xff0c;可能遭遇伪装 无法证明报文的完整性&#xff0c;所以有可能遭篡改 一、通信使用明文&#xff08;不加密&#xff09;&#xff0c;内容可能会被窃听 TCP/…

dpdk 总线设备管理

背景 dpdk版本: 22.11 1、dpdk支持的bus类型注册 注册当前能够处理bus类型,放在全局 rte_bus_list 链表中。 struct rte_bus: A structure describing a generic bus,描述总线类型的结构 注册方法 void rte_bus_register(struct rte_bus *bus); //函数功能: 将支持的bus结…

C++-4

在Complex类的基础上&#xff0c;完成^&#xff0c;>&#xff0c;~运算符的重载 #include <iostream>using namespace std; class Complex {int rel; //实部int vir; //虚部 public:Complex(){}Complex(int rel,int vir):rel(rel),vir(vir){}/* Complex operato…

5、Flink事件时间之Watermark详解

1&#xff09;生成 Watermark 1.Watermark 策略简介 为了使用事件时间语义&#xff0c;Flink 应用程序需要知道事件时间戳对应的字段&#xff0c;即数据流中的每个元素都需要拥有可分配的事件时间戳。 通过使用 TimestampAssigner API 从元素中的某个字段去访问/提取时间戳。…