I have Google 2FA set up for ssh password logins. Works fine, but if possible I'd like to tighten a small security hole: if the password given is correct, it will then ask for the 2FA token. If the password given is incorrect, though, then it will keep asking for the password. This obviously would reveal to an attacker that they have actually discovered the password, even if they can't get in immediately.

For example, if the password is hunter2:

Password: hunter2
Verification code: 


Password: banana

I'd like to set it up so that it asks for the 2FA code in every instance, even when the password is wrong, to close off this attack vector. I'd also like it to send me an alert if the correct password is entered along with an incorrect OTP.

Is this something I can achieve with PAM configuration or would I need to basically write my own module for it?

# PAM configuration for the Secure Shell service

# Standard Un*x authentication.
@include common-auth
auth required pam_google_authenticator.so nullok
# Disallow non-root logins when /etc/nologin exists.
account    required     pam_nologin.so

# Uncomment and edit /etc/security/access.conf if you need to set complex
# access limits that are hard to express in sshd_config.
# account  required     pam_access.so

# Standard Un*x authorization.
@include common-account

# SELinux needs to be the first session rule.  This ensures that any
# lingering context has been cleared.  Without this it is possible that a
# module could execute code in the wrong domain.
session [success=ok ignore=ignore module_unknown=ignore default=bad]        pam_selinux.so close

# Set the loginuid process attribute.
session    required     pam_loginuid.so

# Create a new session keyring.
session    optional     pam_keyinit.so force revoke

# Standard Un*x session setup and teardown.
@include common-session

# Print the message of the day upon successful login.
# This includes a dynamically generated part from /run/motd.dynamic
# and a static (admin-editable) part from /etc/motd.
session    optional     pam_motd.so  motd=/run/motd.dynamic
session    optional     pam_motd.so noupdate

# Print the status of the user's mailbox upon successful login.
session    optional     pam_mail.so standard noenv # [1]

# Set up user limits from /etc/security/limits.conf.
session    required     pam_limits.so

# Read environment variables from /etc/environment and
# /etc/security/pam_env.conf.
session    required     pam_env.so # [1]
# In Debian 4.0 (etch), locale-related environment variables were moved to
# /etc/default/locale, so read that as well.
session    required     pam_env.so user_readenv=1 envfile=/etc/default/locale

# SELinux needs to intervene at login time to ensure that the process starts
# in the proper default security context.  Only sessions which are intended
# to run in the user's context should be run after this.
session [success=ok ignore=ignore module_unknown=ignore default=bad]        pam_selinux.so open

# Standard Un*x password updating.
@include common-password
  • What is your current PAM configuration? – muru Oct 3 '19 at 2:44
  • I just added auth required pam_google_authenticator.so to the top of the PAM config file. In the ssh config I have UsePAM yes, PasswordAuthentication no, ChallengeResponseAuthentication yes, and AuthenticationMethods publickey keyboard-interactive. – xereeto Oct 3 '19 at 3:31
  • 1
    Please show the current PAM configuration. – muru Oct 3 '19 at 3:40
  • pastebin.com/Zsq57gkr – xereeto Oct 3 '19 at 10:46
  • Ok, and the contents of /etc/pam.d/common-auth, as well, please. – muru Oct 3 '19 at 14:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.