the_open_door
coffee
ESEN
← Back to index

fail2ban privesc (actionban)

fail2ban is a service that watches logs (SSH, for example) and automatically bans IPs with too many failed attempts. To ban, it runs an action defined in /etc/fail2ban/action.d/ (typically iptables-multiport.conf), whose actionban field is, literally, a command run as root when a ban happens.

That's the abuse: if a user can modify actionban and also restart the service to apply the new config, they control a command that will run with root privileges. The common case is a sudo -l allowing a fail2ban restart:

(root) NOPASSWD: /etc/init.d/fail2ban restart

The plan: change actionban to something granting persistent privileges (making /bin/bash SUID is the cleanest), apply the config, and force a ban to trigger the action.

# 1) Edit actionban (if the file isn't writable, copy-edit-replace)
#    actionban = chmod u+s /bin/bash
# 2) Apply the new config
sudo /etc/init.d/fail2ban restart
# 3) Cause a ban (many failed SSH attempts)
hydra -l <user> -P rockyou.txt ssh://<ip> -t 64
# 4) When the ban fires, /bin/bash becomes SUID
bash -p        # euid=0 -> root

Caveats. Sometimes the action file isn't directly writable by the user, but the directory is or it can be replaced (copy to /tmp, edit, rename the original and move the modified one). The ban must be triggered actively (a brute force does it) and it's good to restore the original config afterwards so as not to break the service.

How to spot it. Two signals must line up: a sudo -l allowing a fail2ban restart (or a group/permission that lets you touch /etc/fail2ban/action.d/) and effective write over actionban (directly or via the directory, ls -la /etc/fail2ban/action.d/). Without both, editing the action and applying it, there is no vector.

Defence. Don't grant non-admin users sudo control of fail2ban (not even restart), protect action.d/ (root ownership and permissions, non-writable directory), and prevent service accounts from altering the actions. It's a particular case of the general principle: granting control over a service that runs arbitrary commands as root is equivalent to granting root, just like abusing binaries via sudo.

Machines where it's used