Thoughts about PAM
May 25th, 2011In the OpenPAM source code (used by NetBSD, FreeBSD and OSX since Snow Leopard), one can spot in lib/openpam_ttyconv.c:
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTSTP);
sigprocmask(SIG_SETMASK, &sigset, &saved_sigset);
that it misses a third signal that can be triggered interactively, SIGQUIT (C-\ in most terminals). If a user starts an SUID program which doesn’t handle this signal separately, this allows the user to crash the program and avoid the usual timeout on failed attempts. A local brute force attack on passwords could be possible.
All the consumers of this conversation callback, pam_ttyconv (aka misc_conv), the only usable one provided in OpenPAM, could cause this threat.
Under OSX, login is resilient to this signal, and so is passwd as it introduces a delay before closing. Sadly su doesn’t, at least as far as my perception goes (yes, that’s a poor evaluation when considering brute force). One could argue that su ensures that it runs interactively in a tty to prevent scripting, but tools like expect show that ptys are a valid countermeasure.
I understand, or at least hope, that the OpenDirectory stack, involved through pam_opendirectory.so, does prevent such brute force attempts itself. I’d like to find the time and motivation to look at the other BSD-derived operating systems. At least I’d get to look at the source code…
I had a quick look at the situation in GNU coreutils, which provides su under Linux; funnily enough, it turns out that it is not pam-aware, and that Linux vendors maintain patches on top! A bit surprising in 2011… But as far as Linux is concerned, avoiding brute force is simple: use pam_tally.so.
Whilst I still have to look further into it, if you write an application that uses pam to interactively check a user’s password and is therefore SUID (/etc/shadow and all), I would recommend to:
- Make sure the password verification process cannot be spawned too quickly or in parallel within the process, or that a success cannot be identified quickly
- If you delay further attempts in case of failure but allow the user to identify a success quickly, try to ensure that you are running interactively (in a
tty, if possible a trusted one), and block terminal-related signals (SIGINT,SIGQUIT,SIGTSTPjust in case, and give a thought toSIGHUPto fight againstpty-based attacks) - Most importantly, distribute (or recommend to distributors) an appropriate pam configuration for your application: if
pam_tally(or equiv.), enforcing of/etc/securetty, etc. should be involved, state so!
If you administer systems allowing shell access, I would suggest to:
- Review your whole pam stack: the configuration for all services, the extra settings for the backends involved.
- Limit the number of processes and file descriptors for your users!
- If possible, limit the availability of
ptyautomation tools (expectfor example, but unfortunately also Python) and involvenoexec. - Log failed attempts, monitor the logs. With a good password, a brute-force attack involving the creation of one process per attempt will take long (do your own math, that’s years with 100k attempts per second with the entropy of my shell passwords).
But hey, I am not a security expert. And of course, just have very secure passwords :)



