RCE with Mercurial (hg) hooks
Mercurial (hg) is a version control system, a cousin of Git. Like Git, it fires hooks: scripts run automatically when a repository event happens (pre-commit, update, post-pull...). A hook is defined in the repository's or user's .hgrc configuration file:
[hooks]
post-pull = /tmp/shell.shThe vector appears when we can run hg as another user (typically via sudo) over a repository whose configuration we control. If we have a sudo -l like (dev) /usr/bin/hg pull /home/dev/app-production/, running the pull makes Mercurial read the applicable .hgrc and execute the post-pull hook as the target user, giving us execution as them.
# .hgrc with the hook pointing at our script
sudo -u dev /usr/bin/hg pull /home/dev/app-production/A practical detail: the target user must be able to read the .hgrc and the repository. If the original sits in a home they can't reach (permissions), rebuild the environment in a common path like /tmp (mkdir .hg; cp .hgrc .hg/hgrc) to avoid access errors. Mercurial also requires the user to be listed as trusted to honour someone else's .hgrc.
How to detect it. The signature is a sudo hg pull/update in /var/log/auth.log followed, on the host, by the hg process (running as the target user) spawning sh/bash as a child, which is the hook execution (auditd/Sysmon for Linux over execve with ppid=hg), something a legitimate pull never does. On disk, a .hg/hgrc/.hgrc with a [hooks] section pointing at a script in a writable path (/tmp) is the indicator (FIM). The same pattern applies to git with hooks (core.fsmonitor, post-checkout).
Defence. Don't grant sudo over hg (or git) pointing at repositories writable by the attacker; hooks run arbitrary code by design. If unavoidable, restrict with fixed paths and controlled ownership, and distrust the repository's configuration files.
Machines where it's used
- YummyHackTheBox