$ cat writeup.md…
$ cat writeup.md…
avitoctf
Task: A low-privileged SSH account and a PAM root OTP flow expose a trust-boundary flaw in GNU Mailutils configuration. Solution: Override sendmail through the worker's .mailrc, capture the OTP in a FIFO, and feed it to su.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Предоставлены SSH-учётные данные пользователя
worker. Цель — незаметно получить/root/flag.txt.
English summary: Starting from a low-privileged worker shell, obtain the root-only flag. Root authentication through su uses a custom one-time password sent to root's local mailbox.
The usual direct privilege-escalation checks did not provide a route: worker had no useful sudo rights or file capabilities. The productive clue was the custom PAM entry for su:
id sudo -n -l 2>&1 getcap -r / 2>/dev/null cat /etc/pam.d/su cat /usr/local/bin/pam_otp_root.py /usr/bin/mail --version
The relevant PAM configuration was:
auth requisite pam_python.so /usr/local/bin/pam_otp_root.py
For a root login, the module generated nine decimal digits, invoked Mailutils, and only then prompted su for the same value:
p = subprocess.Popen( ["/usr/bin/mail", "-s", "OTP for root login", "root"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
The absolute /usr/bin/mail path prevents a simple PATH hijack, but it does not make the invocation safe. At this point PAM is authenticating a requested identity; su has not yet transitioned to root. GNU Mailutils 3.15 therefore runs in the worker context and reads /home/worker/.mailrc.
Mailutils accepts the following user configuration:
set sendmail=/home/worker/sm.sh
This changes its delivery backend to an attacker-controlled executable. The OTP crosses a security boundary through software whose behavior is still configurable by the untrusted caller. It is therefore a trust-boundary and configuration flaw, not a weakness in OTP generation.
An unusual movable SGID-mail helper and an injectable backup script suggested a longer chain, but the backupuser cron job never ran because PAM rejected that account. Exim aliases, .forward, transports, expansions, and queue modes either executed as worker or were restricted. These paths were decoys compared with intercepting the OTP directly at its source.
...
$ grep --similar