Password Authentication in Python Paramiko Fails, But Same Credentials Work in Ssh/Sftp Client

Password authentication in Python Paramiko fails, but same credentials work in SSH/SFTP client

Your server is using a keyboard-interactive authentication, not a simple password authentication.

Normally Paramiko is smart enough to fallback to the keyboard-interactive authentication, when the password authentication fails and the keyboard-interactive prompt has one field only (likely a password).

The problem is that your server behaves, as if the password authentication succeeded.

You can explicitly make Paramiko try the keyboard-interactive authentication using this code:

def handler(title, instructions, fields):
if len(fields) > 1:
raise SSHException("Expecting one field only.")
return [password]

transport = paramiko.Transport('example.com')
transport.connect(username='myuser')
transport.auth_interactive(username, handler)

Paramiko SFTP will not authenticate with correct username and password but GUI SFTP client success with keyboard-interactive authentication

It seems that your server supports only keyboard-interactive authentication. While you are using password authentication in your Python/Paramiko code.

Try using the high-level Paramiko API, the SSHClient. It automatically uses your password for keyboard-interactive authentication.

ssh = paramiko.SSHClient()
ssh.connect(host, port=port, username=username, password=password)

Also the SSHClient correctly validates your server's host key, what the low-level Transport API does not (what is a security flaw).


It turned out that the above does not work either, as the server behaves strangely.

This workaround worked:

Paramiko/Python: Keyboard interactive authentication

Connect with Python Paramiko to SSH server that in addition to password prompt requires submitting an keyboard interactive banner with Enter key

Your server seems to issue two keyboard-interactive authentication challenges

  • First, a prompt for a password
  • Second, a banner with no prompts.

So you will have to do something like this:

def handler(title, instructions, fields):
if len(fields) == 1:
return [password]
else:
return []

transport = paramiko.Transport('example.com')
transport.connect(username='myuser')
transport.auth_password(username, password)
transport.auth_interactive(username, handler)

Some references:

  • Paramiko/Python: Keyboard interactive authentication
  • SSH with 2FA in Python Using Paramiko
  • Multi-factor authentication (password and key) with Paramiko

Further, as you have find out, you need to escape the \ in the username.

Passwordless SSH connection with Paramiko fails where as with SSH works

Your ssh connection works, because it uses a private key from ~/.ssh/id_rsa_c2c (as configured in ssh_config). The .ssh folder and ssh_config file serve as a configuration for OpenSSH toolset (ssh in this case). You cannot expect that other SSH clients/libraries will use OpenSSH configuration files. They won't, in general.

If you want to use public key authentication with Paramiko, use key_filename argument of SSHClient.connect.

See also How to ssh connect through python Paramiko with ppk public key.

Though Paramiko, in particular, would use a key file, if it had a common name like id_rsa, id_dsa, etc. See Force password authentication (ignore keys in .ssh folder) in Paramiko in Python for exactly opposite problem.


Obligatory warning: Do not use AutoAddPolicy, unless you do not care about security. You are losing a protection against MITM attacks this way.

For a correct solution, see Paramiko "Unknown Server"
.

Paramiko AuthenticationException issue

The ssh server on the remote device denied your authentication. Make sure you're using the correct key, the public key is present in authorized_keys, .ssh directory permissions are correct, authorized_keys permissions are correct, and the device doesn't have any other access restrictions. It hard to say what's going on without logs from the server.

[EDIT] I just looked back through your output, you are authenticating using None authentication. This usually isn't ever permitted, and is used to determine what auth methods are allowed by the server. It's possible your server is using host based authentication (or none at all!).

Since auth_none() is rarely used, it's not accessible from the SSHClient class, so you will need to use Transport directly.

transport.auth_none('root') 


Related Topics



Leave a reply



Submit