Vendor: Pulse Secure
Vendor URL: https://www.pulsesecure.net/
Versions affected: Pulse Connect Secure (PCS) 9.1Rx or below
Systems Affected: Pulse Connect Secure (PCS) Appliances
CVE Identifier: CVE-2020-8260
Advisory URL: https://kb.pulsesecure.net/articles/Pulse_Security_Advisories/SA44601
Risk: 7.2 High CVSS:3.0/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
Richard Warren - richard.warren[at]nccgroup[dot]com
David Cash – david.cash[at]nccgroup[dot]com
The Pulse Connect Secure appliance suffers from an uncontrolled gzip extraction vulnerability which allows an attacker to overwrite arbitrary files, resulting in Remote Code Execution as root.
Successful exploitation by an authenticated administrator results in Remote Code Execution on the underlying Operating System with root privileges. An attacker with such access will be able to circumvent any restrictions enforced via the web application, as well as remount the filesystem, allowing them to create a persistent backdoor, extract and decrypt credentials, or pivot into the internal network.
PCS allows administrative users to import and export archived configurations via the
/dana-admin/cached/config/import.cgi CGI script. These configurations are compressed using gzip and encrypted using a hardcoded key. The user can then download the encrypted configuration file for later restoration.
During the restoration process, the user-supplied (previously exported) configuration file is decrypted using the
configdecrypt binary. After decryption, the file is unpacked using tar. The following command is used to extract the configuration files from the decrypted archive:
tar -C $path -xzf $path/config.exp --strip=1 >/dev/null 2>&1
No restriction on what files are extracted is carried out, other than that the file(s) will be extracted into the directory specified by
$path. On systems before PCS 9.1R4.0, the
$path variable was set to
/home/runtime/ meaning that any file on the (read-write mounted) data partition could be overwritten. On later systems this was changed to
/home/runtime/tmp/ meaning that only files within the
tmp directory could be overwritten. However, in both cases this is enough to achieve code execution.
Proof of Concept(s)
On systems before PCS 9.1R4, it was possible to overwrite any file on the
/home/runtime/ partition. Although this partition does not contain any executable binaries (these are instead stored on the readonly partition), we identified a few ways in which code execution could be triggered.
The Linux kernel Watchdog agent is installed on PCS with its configuration file stored in the data partition at
Looking at the man page for Watchdog, we came across the
test-binary directive. This configuration parameter specifies a binary that should be executed to carry out user-defined tests.
By overwriting the
watchdog.conf file with a
test-binary parameter pointing to our custom binary we could achieve code execution with the privileges of the watchdog agent (root). To demonstrate this, we wrote an exploit which used the watchdog test-binary to bootstrap the dropbear SSH server with our own SSH key. Similar could also be achieved using OpenSSH, allowing for SOCKS proxying via the compromised VPN endpoint.
The following output shows the structure of our malicious gzip file:
~ ./configdecrypt myconf.cfg myconf.gz
~ tar -zxvf myconf.gz
The following shows the modified
-- SNIP --
test-binary = /home/runtime/kwatchdog/deploybear
test-timeout = 3600
When the watchdog is enabled in the admin UI via the
/dana-admin/sysinfo/sysoptions.cgi page, the SSH agent is bootstrapped and code execution is achieved.
The PostgreSQL database is installed on PCS and the configuration and data files are stored within the data partition at
Reading the PostgreSQL documentation, we came across the
shared_preload_libraries option, which is specified in the
postgresql.conf file. As per the documentation, “This variable specifies one or more shared libraries to be preloaded at server start”.
By creating a malicious shared library, and modifying the
shared_preload_libraries configuration to point to our uploaded library we could achieve code execution when PostgreSQL is restarted.
The following screenshot shows the overwritten
postgresql.conf file, with the path to our malicious shared library containing a reverse shell.
However, when we restarted PostgreSQL, the shared library was not loaded. After some debugging we realised that this was because our arbitrary file write primitive writes the file as
root, whilst PostgreSQL runs as
postgres. This means that
postgres will not be able to read the shared library file when it starts. To get round this, we exploited the bug twice. First, we used the file write to modify the
log_filename option, setting the logfile to
/home/runtime/libshell.so. This causes PostgreSQL to create the
libshell.so file, owned by the
postgres user. We then exploit the bug again, this time overwriting the
libshell.so file with our reverse shell, and changing the
shared_preload_libraries option to point at our shared library. Now PostgresSQL will be able to read the file as it is owned by
Finally, when PostgreSQL is restarted via the
/dana-admin/sysinfo/sysinfo.cgi CGI script, the reverse shell is executed, and code execution is achieved under the
Template Toolkit (strikes again)
On systems running PCS 9.1R4 or above, the file-write primitive is restricted to files within the
/home/runtime/tmp/ folder. However it is still possible to achieve code execution using the Perl template overwrite method first documented by Orange Tsai and Meh Chang.
PCS uses Perl Template Toolkit to compile and render templates at runtime. Compiled templates are stored in the
/home/runtime/tmp/tt/ folder. By overwriting the
/home/runtime/tmp/tt/setcookie.thtml.ttc, using our gzip file write primitive, arbitrary Perl code execution can be triggered when visiting the
The following output shows the structure of our malicious gzip file:
~ ./configdecrypt config.exp decrypted.exp
~ tar -zxvf decrypted.exp
~ cat tmp/tt/setcookie.thtml.ttc
When a GET request is made to
/dana-na/auth/setcookie.cgi, the command specified in the
PULSE_CMD HTTP header is executed with root privileges.
Upgrade to Pulse Connect Secure (PCS) 9.1R9, or later.
2020-06-02: Issue reported to vendor
2020-10-22: Pulse Connect Secure (PCS) version 9.1R9 released
2020-10-26: Advisory released by Pulse Secure
2020-10-26: NCC Group advisory released
About NCC Group
NCC Group is a global expert in cybersecurity and risk mitigation, working with businesses to protect their brand, value and reputation against the ever-evolving threat landscape. With our knowledge, experience and global footprint, we are best placed to help businesses identify, assess, mitigate & respond to the risks they face. We are passionate about making the Internet safer and revolutionizing the way in which organizations think about cybersecurity.
Published Date: 26/10/2020
Written by: Richard Warren & David Cash