Pterodactyl Security Announcement: January 31st, 2019

At approximately 07:00 -0800 on Wednesday, January 30th, 2019 we were made aware of a security vulnerability in the installation process for servers via our public GitHub repository for Pterodactyl. The issue was tagged as a P: Critical bug, and quickly circulated in our internal moderation channel while we sought to reproduce it.

Upon further investigation it was discovered that the issue affected a significantly more extreme scope than was initially reported. At that time the public issue was pulled from our repository due to the new severity and impact.

Bug Details

Servers spun up via Pterodactyl run in isolated Docker containers and have a restricted filesystem and cannot access host files (aside from the host directory holding the server files). However, due to architectural decisions early in Pterodactyl's development the Daemon and standalone SFTP server use a root privileged user to manage containers, files, and other system level functionality for servers.

All versions of Pterodactyl's daemon have used a single function to perform path resolution and determine if the file being requested is actually a file within the given server's directory. In a very simple sense, this was acting much like a chroot jail.

However, due to a glaring oversight in the checking code symlinks were not being resolved to their true path, only to the relative path. Given a malicious symlink path the Daemon would determine that the relative path was correct, allowing the system to open that symlink and thus have access to a file or folder outside the scope of the server's directory.

Attack Vector

This bug has a minimal-effort attack vector allowing a malicious user to craft malicious symlinks for their server, which can then be access via the built-in file manager, file download API, or via SFTP.

Server processes are unable to properly resolve these files due to the Docker based setup. In addition, Daemon instances running inside a Docker container themselves were limited in attack vector to the filesystem available in the container.

Resolution

Later in the evening on the 30th a fix was committed into the development branch for the Daemon and was subsequently tagged and released after testing on the 31st.

At the same time the standalone SFTP server was patched. Due to the severity and wide-reaching impacts of this bug the fix was additionally backported to the v0.5.X daemon branch for hosts who may still be reliant on the older code base.

commit 3f9186e4742bb107dc04e817d3aad468a8487407
Author: Dane Everitt <dane@daneeveritt.com>
Date:   Wed Jan 30 18:35:05 2019 -0800

    Fix path resolution for server files

diff --git a/src/controllers/server.js b/src/controllers/server.js
index 19368a5..cf814d2 100644
--- a/src/controllers/server.js
+++ b/src/controllers/server.js
@@ -580,7 +580,11 @@ class Server extends EventEmitter {

         let returnPath = dataPath;
         if (!_.isUndefined(location) && _.replace(location, /\s+/g, '').length > 0) {
-            returnPath = Path.join(dataPath, Path.normalize(Querystring.unescape(location)));
+            try {
+                returnPath = Fs.realpathSync(Path.join(dataPath, Path.normalize(Querystring.unescape(location))));
+            } catch (err) {
+                // ignore error, will just use the default path
+            }
         }

         // Path is good, return it.

Patching Your Systems

To patch this bug on your systems simply update your Daemon instances, as well as the standalone SFTP server if you are using that.

Daemon upgrade documentation: https://pterodactyl.io/daemon/upgrade/0.6.html

Standlone SFTP documentation: https://pterodactyl.io/daemon/standalone_sftp.html

Acknowledgements

Thank you to GitHub user GwtLabs who initially reported this issue to us on GitHub.

Additionally, thank you to Michael Parker and Trixter#0001 for helping track down and ultimately patch the bug on the SFTP server and Daemon respectively.

Comments