About two weeks ago, on December 17th, Citrix released a workaround for a critical vulnerability in its Application Delivery Controller (ADC) and Gateway products [1]. These are products that Citrix acquired from NetScaler in 2005, and the NetScaler name is still commonly used.

Last week, on December 23rd, Positive Technologies released a blog post with additional information, emphasizing the impact of the vulnerability [2]. This blog post affirmed that the vulnerability is critical and needs to be addressed quickly. CVE-2019-19781 is used to track this vulnerability.

Due to the urgency of this problem, and holidays affecting about 70% of the globe these two weeks, we will have a special webcast to discuss this vulnerability.

Luckily, there is no public “Proof of Concept (PoC)” exploit available yet, and we have not detected any exploitation of the vulnerability yet. You may have a bit more time to apply the workaround published by Citrix. During a quick review of the Citrix ADC code this week, we found several weaknesses and were able to exploit them to at least upload files to the system. This did not require any special tools or advanced skills. A determined individual should be able to find a full exploit in about a week. The code, as well as the system configuration, showed several obvious weaknesses. This is unlikely the last time you will have to patch these devices.

According to Citrix’s advisory, exploitation of the vulnerability does not require authentication and allows arbitrary code execution. The affected products can be deployed in a large number of configurations, and not all configurations may be vulnerable. But neither Citrix nor Positive Technologies provide any guidance to identify vulnerable configurations. Most likely, configurations that expose the Citrix web interface to outside users are vulnerable. This would affect the use of Citrix Gateway as an SSLVPN. Still, it could very well be used in other scenarios, for example, if Citrix ADC is used to restrict access to internal APIs or web applications.

The best “hint” as to the nature of the flaw is the workaround Citrix published [3]:

The rule first checks if the URL contains the string “/vpns/." Next, it checks if the user is either not connected to the SSLVPN, or if the URLs include the string "/../”. The “decode_using_text_mode” overwrites the default URL encoding. This likely indicates that the ‘/’ and ‘.’ characters can not be URL encoded to make the exploit work. It is important to note that the “/vpns/” string alone is blocked in the URL. You should not include the “/../” string if you translate this signature to other security devices.

Citrix notes that this policy may block some valid requests as well. The "/vpns/scripts/" directory, for example, is used to serve browser plugins. Access to this directory is blocked by the suggested policy. If you are using the Citrix ADC in front of other web applications, any URLs that contain "/vpns/” are part of the patch are blocked.

The last part (“/../") is typical for a directory traversal vulnerability. Directory traversal vulnerabilities come in many shapes and severities. Attackers typically use them to gain access to restricted resources, and the impact depends a lot on what resources are accessible.

A simple example (and this is NOT necessarily how it works here): A web application restricting access to the “/admin” URL can be fooled into providing access to unauthenticated users as long as they use a URL like “/somethingelse/../admin." The URL no longer starts with "/admin," and a web application is vulnerable if it does not parse URLs correctly. Directory traversal issues can also happen if the application executed files on the system. For example, the developer creates a "tools" directory with various scripts the user is allowed to run. The application then uses code like:

execute(“/tools/$script”)

An attacker could now supply a script like “../usr/bin/bash” to execute additional commands. This command injection vulnerability does take advantage of directory traversal.

Typically, simple "blocklists" like the one Citrix implemented here are not ideal. An attacker may be able to find alternative paths to the vulnerable script, or the attacker uses a different encoding technique to bypass the rule. At this point, we do not know enough about this vulnerability to discern if the rule is sufficient or not. Citrix has not announced any plans for an actual patch. Based on our review of the code, a patch will likely reveal sufficient details about the vulnerability to make it trivial to find an exploit. The policy was likely designed to block the exploit while revealing as little as possible about the vulnerability.

After applying the recommended policy, any attacks should be logged in the Apache access and error log. For example:

Monitor your systems for any exploit attempts. A quick “grep” for requests that contain “vpns” and “..” should tell you if there are any.

Consider additional steps, for example, if you have additional security devices ahead of Citrix ADC.

Monitor any abnormal activities from the Citrix ADC and Gateway, particularly from those devices towards the internal network hosts.

Even if you do not use Citrix, take a moment to check up on your other perimeter devices to make sure they are up to date. Last year has seen several critical vulnerabilities in similar devices. For example, there are still plenty of unpatched Fortinet devices out there that suffer from a path traversal vulnerability. Exploit code is readily available and has been used in the wild. The Fortinet vulnerability isn't a "remote code execution" vulnerability, but can easily be used to retrieve privileged account credentials from the system.

Hello Dr. Ullrich,
Do you by any chance know where the logs would be prior to the fix? In testing after the fix, we are not seeing the remote attack system IP address in either httperror or httpaccess logs. I see in your example that the address is from 127.0.0.2, but was not sure if this was because you are testing from the host itself, or if the log will always show the localhost IP.
Cheers,
Leon