SafeBreach Labs discovered a new vulnerability in Atlassian Jira Server and Confluence Server software.
In this post, we will demonstrate how this vulnerability can be used in order to achieve privilege escalation, persistence and in some cases defense evasion by loading an arbitrary unsigned DLL into a service that runs as SYSTEM.
Additionally, we will present some of the potential malicious actions that could be undertaken by exploiting this vulnerability in the Jira Server and Confluence Server software.
Atlassian Jira Server / Confluence Server
Atlassian Jira Server and Confluence Server allows the user to host the Jira and Confluence services on-premise on a Windows machine.
Part of the services is executed as “NT AUTHORITY\SYSTEM,” which provides it with very powerful permissions.
Apache Tomcat (sometimes simply “Tomcat”) is an open source implementation of the Java Servlet, JavaServer Pages, Java Expression Language and WebSocket technologies.
Tomcat provides a “pure Java” HTTP web server environment in which Java code can run.
Part of the Jira Server / Confluence Server are implemented using Apache Tomcat.
In this post, we describe the vulnerability we found in the Tomcat component in the Jira / Atlassian Server software. We then demonstrate how this vulnerability can be exploited to achieve privilege escalation, gaining access with SYSTEM level privileges.
Note: The Root cause of the vulnerability is identical on both software (Jira Server and Confluence Server). We will use Confluence Server to describe the vulnerability, but it’s the same on Jira Server as well.
In our initial exploration, we targeted the “Commons Daemon Service Runner” service (tomcat9.exe) based on the assumption that a service with high-permission-level access would provide the capability to induce privilege escalation.
After the Commons Daemon Service Runner service started, it executed tomcat9.exe as NT AUTHORITY\SYSTEM.
The service tries to load a missing DLL file, which eventually were loaded from the
c:\python27 directory – which is in our PATH environment variable:
As you can see, the service was trying to load a missing DLL file
(MSVCR120.dll), which eventually were loaded from the c:\python27 directory – our PATH environment variable.
Demonstrating a DLL hijacking vulnerability:
In our VM, the c:\python27 has an ACL which allows any authenticated user to write files onto the ACL. This makes the privilege escalation simple and allows a regular user to write the missing DLL file and achieve code execution as NT AUTHORITY\SYSTEM.
It is important to note that an administrative user or process must (1) set the directory ACLs to allow access to non-admin user accounts, and (2) modify the system’s PATH variable to include that directory.
In order to test this privilege escalation vulnerability, we compiled a DLL (unsigned) which writes the following to the filename of a txt file:
- The username which executed it.
- The name of the DLL file.
We were able to load an arbitrary DLL and execute our code as NT AUTHORITY SYSTEM.
Root Cause Analysis
Once the OpenHardwareMonitor library is loaded, it tries to load a DLL using LoadLibraryExW:
It is using 0 for the dwFlags parameter.
According to MSDN’s LoadLibraryExW documentation:
If no flags are specified, the behavior of this function is identical to that of the LoadLibrary function.
As we can see in the screenshots, there are two root causes for the vulnerability:
- The lack of safe DLL loading. The code is using LoadLibraryExW without flags which is identical to LoadLibraryW, instead of using LoadLibraryExW which allows defining the search order using certain flags, such as LOAD LIBRARY SEARCH SYSTEM32 which searches the DLL only in the System32 folder, avoiding the scenario of searching the DLL in the PATH variable.
- No digital signature validation is made against the binary (e.g. using WinVerifyTrust.) The program doesn’t validate whether the DLL that it will load is signed. Therefore, it will load an arbitrary unsigned DLL without any hesitation.
Potential Malicious Uses and Impact
Below we show three possible ways that an attacker can leverage the vulnerability we discovered and documented above.
Signed Execution, Defense Evasion and Whitelisting Bypass
The CVE-2019-20406 and CVE-2019-20400 vulnerabilities gives attackers the ability to load and execute malicious payloads using a signed service. This ability might be abused by an attacker for different purposes such as execution and evasion, for example:
- Application Whitelisting Bypass
- Signature Validation Bypassing
The vulnerability gives attackers the ability to load and execute malicious payloads in a persistent way, each time the service is loaded. That means that once the attacker drops a malicious DLL in a vulnerable path, the service will load the malicious code each time it is restarted.
The service provides the attacker with the ability to operate as NT AUTHORITY\SYSTEM.
- The usage of Tomcat in Confluence on the Microsoft Windows operating system before version 7.0.5, from version 7.1.0 before version 7.1.1 allows local system attackers who have permission to write a dll file in a directory in the global path environmental variable variable to inject code & escalate their privileges via a DLL hijacking vulnerability.
- The usage of Tomcat in Jira before version 8.5.2 allows local attackers with permission to write a dll file to a directory in the global path environmental variable can inject code into via a DLL hijacking vulnerability.
Aug 28th, 2019 – Vulnerabilities reported to Atlassian using BugCrowd
Aug 29th, 2019 – BugCrowd asked for a clarification
Aug 29th, 2019 – SafeBreach sent a more detailed PoC
Sep 4th, 2019 – Atlassian confirmed the vulnerability.
Oct 22nd, 2019 – SafeBreach asked Atlassian for a disclosure timeline and a CVE-IDs.
Nov 4th, 2019 – Atlassian mentioned that they can’t provide this information yet, and asked to open a support ticket in their support system.
Nov 11th, 2019 – SafeBreach reported the issue on Atlassian’s support system.
Nov 18th, 2019 – Atlassian mentioned that they opened two internal tickets and both are awaiting resolution.
Nov 20th, 2019 – SafeBreach asked Atlassian again for a disclosure timeline and CVE-IDs.
Nov 22nd, 2019 – Atlassian’s support forwarded the request to the security team.
Dec 10th, 2019 – Atlassian mentioned that they didn’t hear back from the security team yet.
Dec 19th, 2019 – Atlassian mentioned that they are waiting for CVE-IDs.
Dec 24th, 2019 – Atlassian freezed the ticket for a few days as the new CVE range they were expected hasn’t been released yet.
Feb 5th, 2020 – Atlassian mentioned that the security team reached out and provided CVE-2019-20406 (CONFSERVER-59428 ) and CVE-2019-20400 (JRASERVER-70407 )