Unable to use a user for a SSH connection configured to bypass MFA in a MFA-enabled environment

86 views
Skip to first unread message

Alvaro Alonso

unread,
Jul 4, 2017, 10:07:46 AM7/4/17
to sshj-users
Hi there,

I have enabled SSH to support Multi-factor authentication. In this sense, I have configured SSH so that it uses the following authentication methods


AuthenticationMethods publickey,keyboard-interactive



I have some ssh configuration in the PAM configuration directory (pam.d/ssh)

@include google-authenticator-test
# PAM configuration for the Secure Shell service
# Standard Un*x authentication.
# 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.




The included file in the pam.d/ssh

# cat google-authenticator-test


auth sufficient pam_succeed_if
.so quiet user ingroup users-without-mfa
auth required pam_google_authenticator
.so


This is, I have configured in the PAM an entry to make users belonging to "users-without-mfa" be authenticated without MFA.

When I try manually the SSH connection with this user, it works successfully. I have followed the debug logs, and I noticed the following

  * It firstly tries connecting with the privatekey I provided for that user.

  * It then tries connecting with keyboard-interactive. Since PAM has been configured to bypass the authentication for users belonging to "users-without-mfa", I also get a success

debug3: remaining preferred: keyboard-interactive,password
debug3
: authmethod_is_enabled publickey
debug1
: Next authentication method: publickey
debug1
: Trying private key: mytest
debug3
: sign_and_send_pubkey: RSA SHA256:zNUQaDikkd9RyU6fKrcC8u5DtaPNQuDwg0hzGg0f/MY
debug3
: send packet: type 50
debug2
: we sent a publickey packet, wait for reply
debug3
: receive packet: type 51
Authenticated with partial success.
debug2
: key: mytest ((nil)), explicit
debug1
: Authentications that can continue: keyboard-interactive
debug3
: start over, passed a different list keyboard-interactive
debug3
: preferred gssapi-keyex,gssapi-with-mic,publickey,keyboard-interactive,password
debug3
: authmethod_lookup keyboard-interactive
debug3
: remaining preferred: password
debug3
: authmethod_is_enabled keyboard-interactive
debug1
: Next authentication method: keyboard-interactive
debug2
: userauth_kbdint
debug3
: send packet: type 50
debug2
: we sent a keyboard-interactive packet, wait for reply
debug3
: receive packet: type 60
debug2
: input_userauth_info_req
debug2
: input_userauth_info_req: num_prompts 0
debug3
: send packet: type 61
debug3
: receive packet: type 52
debug1
: Authentication succeeded (keyboard-interactive).


However, the client throws an "Exhausted authenticated methods" error when trying to authenticate using this user.

Is there anything I should configure to get this working?

BR,
Alvaro

Jeroen van Erp

unread,
Jul 4, 2017, 10:12:54 AM7/4/17
to sshj-...@googlegroups.com
Hi Alvaro,

What is the client/server side logging when attempting a connection with SSHJ? DId it work before setting this up?

Regards,
Jeroen

--
You received this message because you are subscribed to the Google Groups "sshj-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sshj-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alvaro Alonso

unread,
Jul 5, 2017, 9:23:21 AM7/5/17
to sshj-users
Hi Jeroen,

I am not using directly the library, but through another tool which actually uses sshj.

I have done the following steps:

1. I have cloned the sshj repo, and I have edited an existing integration tests to try it against my machine. Let me tell you the configuration I tried


public class IntegrationTest {

     
@Test // Should only be enabled for testing against VM
     
public void shouldConnect() throws IOException {
         
SSHClient sshClient = new SSHClient(new DefaultConfig());
         sshClient
.addHostKeyVerifier(new OpenSSHKnownHosts(new File("/Users/mytestuser/.ssh/known_hosts")));
         sshClient
.connect("192.168.2.3");

         
//sshClient.authPublickey("mytestuser");
         
List<AuthMethod> authMethodList = new ArrayList();
         authMethodList
.add(new AuthPublickey(sshClient.loadKeys("/Users/mytestuser/.ssh/id_rsa")));
         authMethodList
.add(new AuthKeyboardInteractive(new PasswordResponseProvider(new PasswordFinder() {

             
@Override
             
public char[] reqPassword(Resource<?> resource) {
                 
return new char[0];
             
}

             
@Override
             
public boolean shouldRetry(Resource<?> resource) {
                 
return false;
             
}

         
})));
         sshClient
.auth("mytestuser", authMethodList);

         assertThat
("Is connected", sshClient.isAuthenticated());
   
}
}




If I try the configuration specified above, the connection is done successfully.

The issue I see here is that I have to know in advance that the target has been configured for a multi-factor authentication, to be able to add more authentication methods when doing the connection.

Or is there a way to autodiscover the AuthenticationMethods required by the server when opening the connection (I mean, should I perform the auth operation using another way than having to manually specify the corresponding auth methods?)

BR,
Alvaro
To unsubscribe from this group and stop receiving emails from it, send an email to sshj-users+...@googlegroups.com.

Jeroen van Erp

unread,
Jul 5, 2017, 10:17:02 AM7/5/17
to sshj-...@googlegroups.com
Hi Alvaro,

Basically the client needs to know how to authenticate with the host.

There are some tricks in the SSH protocol to find out which methods are supported, for instance you can authenticate with the 'none' authentication. This will then return the supported authentication methods. However you still then need to configure the ones you want to use to connect to a host. 

However you could also implement your own TwoFactorAuthMethod that does what you need. 

To unsubscribe from this group and stop receiving emails from it, send an email to sshj-users+unsubscribe@googlegroups.com.

John Slankas

unread,
Nov 21, 2018, 9:13:37 PM11/21/18
to sshj-users
While this thread is rather old, I'd like to add this following note for other users who run across this problem.  Thank you - John


I was able to authenticate with a public key followed by an MFA token with this code fragment:

        final SSHClient ssh = new SSHClient();
        ssh.addHostKeyVerifier(new PromiscuousVerifier());
        ssh.connect("10.0.1.1");
        Session session = null;
        try {
        AuthKeyboardInteractive aki = new AuthKeyboardInteractive(new ChallengeResponseProvider() {
@Override
public boolean shouldRetry() {
return false;
}
@Override
public void init(Resource resource, String name, String instruction) {
}
@Override
public List<String> getSubmethods() {
return new ArrayList<String>();
}
@Override
public char[] getResponse(String prompt, boolean echo) {
return mfaCode.toCharArray();
}
});
            ssh.auth("userName", new AuthPublickey(new KeyPairWrapper(kp)), aki);

Reply all
Reply to author
Forward
0 new messages