Last month, a critical vulnerability in Citrix ADC and Citrix Gateway was published under CVE-2019-19781. The vulnerability caught our attention as it suggested that an unauthenticated adversary could leverage it to compromise the device. Although the original discovery was made by Positive Technologies and Paddy Power Betfair, there were no details publicly available on how to exploit this, as such this warranted further research.
Vulnerability Analysis
Although there were no publicly available details on how to exploit this issue, the mitigation advisory from Citrix revealed a potential clue to the type of vulnerability that it was.
From this information we can see the path where presumably the vulnerability exists (/vpns/) and that is a possible directory traversal vulnerability. With this in mind, we began to look for definitions of the /vpns path in the httpd.conf file and discovered that the /vpn/portal/scripts/ is handled by the NetScaler::Portal::Handler Perl Module (Handler.pm).
Several scripts were contained in this directory, but since this vulnerability was a potential directory traversal we opted to investigate any potential code paths to file write operations.
This led to the discovery of the following code in the UsersPrefs perl module:
```
sub csd {
my $self = shift;
my $skip_read = shift || "";
# Santity Check
my $cgi = new CGI;
print "Content-type: text/html\n\n";
// Username variable initialized by the NSC_USER HTTP Header
my $username = Encode::decode('utf8', $ENV{'HTTP_NSC_USER'}) || errorpage("Missing NSC_USER header.”); <- MARK THIS
$self->{username} = $username;
...
$self->{session} = %session;
// Constructing the path from the username.
$self->{filename} = NetScaler::Portal::Config::c->{bookmark_dir} . Encode::encode('utf8', $username) . '.xml’;
if($skip_read eq 1) {
return;
}
```
In short, this code essentially builds a path from from the NSC_USER HTTP header without any sanitisation. Consequently, any script that calls the csd function, will be able to trigger the directory vulnerability.
Almost all the scripts used this function, however the most interesting one to us was the newbm.pl script file:
```
my $cgi = new CGI;
print "Content-type: text/html\n\n";
my $user = NetScaler::Portal::UserPrefs->new();
my $doc = $user->csd();
...
my $newurl = Encode::decode('utf8', $cgi->param('url'));
my $newtitle = Encode::decode('utf8', $cgi->param('title'));
my $newdesc = Encode::decode('utf8', $cgi->param('desc'));
my $UI_inuse = Encode::decode('utf8', $cgi->param('UI_inuse'));
...
my $newBM = { url => $newurl,
title => $newtitle,
descr => $newdesc,
UI_inuse => $UI_inuse,
};
...
```
The script creates an array with information from several parameters and then later on, calls the filewrite function which will write the content to an XML file on disk.
```
if ($newBM->{url} =~ /^\/){
push @{$doc->{filesystems}->{filesystem}}, $newBM;
} else { # bookmark
push @{$doc->{bookmarks}->{bookmark}}, $newBM;
}
// Writing XML file to disk
$user->filewrite($doc);
```
Essentially, we have a partial file write primitive where we control the path but not the file extension, and control some content inside the xml file. With this vulnerability alone there was little we could do, but after seeing an article by Craig Yong, it highlighted a potential avenue for exploitation using the Perl Template Toolkit.
With further research, we discovered it was possible to insert specific instructions on the XML file, that if parsed by the template engine could be used to execute commands.
An example of the template parsing can be found below:
Revisiting our exploit, we now have a partial file write primitive which we can use to inject Perl Template Toolkit instructions, but still require a method to force a script to parse the template.
Finding all the references on the code that actually used the templates, the Handler.pm module looked promising:
The $tmplfile variable is constructed from the HTTP Request Path and a new template is built and processed for that file.
Copying the test.xml file we previously created to the templates directory, we can trigger the template parsing.
To summarise, In order to exploit the vulnerability the following steps should be followed:
Discover a way to execute perl code through the template (Requires a bypass),
Write crafted XML file on the templates directory using the path traversal,
Browse to the uploaded XML file, triggering the template parsing.
The last piece of the puzzle is using the template to execute arbitrary commands, which in the default configuration “is not” possible. There is an undocumented feature which allows arbitrary perl code to be executed but at the current time, we don’t plan on documenting this technique. However, using this information security teams should have sufficient details to reproduce the issue but without the granular details to execute code.
Due to the number of devices impacted, MDSec have decided to not provide a ready made exploit for this vulnerability, however we are aware of multiple actors who have now weaponised this vulnerability and felt it important to share this research so others can take appropriate action.
A demonstration of the exploitation can be shown below:
Mitigation
Citrix released a mitigation to prevent exploitation of this issue as documented in Mitigation Steps for CVE-2019-19781. We strongly recommend that any Citrix ADC users apply this mitigation as an immediate priority.
Furthermore, detection of exploitation attempts can be recognised by alerting on URLs containing a POST request with the “/vpns/” and “/../” strings, followed by a GET request to a file ending with the xml extension as highlighted by @buffaloverflow.
This blog post was written by Rio Sherri.
暂无评论