Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verify host key with pysftp

I am writing a program using pysftp, and it wants to verify the SSH host Key against C:\Users\JohnCalvin\.ssh\known_hosts.

Using PuTTY, the terminal program is saving it to the Registry [HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys].

How do I reconcile the difference between pysftp and PuTTY?

My code is:

import pysftp as sftp  def push_file_to_server():     s = sftp.Connection(host='138.99.99.129', username='root', password='*********')     local_path = "testme.txt"     remote_path = "/home/testme.txt"      s.put(local_path, remote_path)     s.close()  push_file_to_server() 

The Error Response I am receiving is:

E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp__init__.py:61: UserWarning:
Failed to load HostKeys from C:\Users\JohnCalvin.ssh\known_hosts.
You will need to explicitly load HostKeys (cnopts.hostkeys.load(filename)) or disableHostKey checking (cnopts.hostkeys = None). warnings.warn(wmsg, UserWarning) Traceback (most recent call last): File "E:\OneDrive\Python\GIT\DigitalCloud\pysftp_tutorial.py", line 14, in push_file_to_server() File "E:\OneDrive\Python\GIT\DigitalCloud\pysftp_tutorial.py", line 7, in push_file_to_server s = sftp.Connection(host='138.99.99.129', username='root', password='********') File "E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp__init__.py", line 132, in init self._tconnect['hostkey'] = self._cnopts.get_hostkey(host) File "E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp__init__.py", line 71, in get_hostkey raise SSHException("No hostkey for host %s found." % host) paramiko.ssh_exception.SSHException: No hostkey for host 138.99.99.129 found. Exception ignored in: > Traceback (most recent call last): File "E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp__init__.py", line 1013, in del self.close() File "E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp__init__.py", line 784, in close if self._sftp_live: AttributeError: 'Connection' object has no attribute '_sftp_live'

like image 786
Gabriel Theodoulos Avatar asked Aug 14 '16 05:08

Gabriel Theodoulos


People also ask

How to disable host key checking in pysftp?

If you wish to disable host key checking (NOT ADVISED) you will need to modify the default CnOpts and set the . hostkeys to None. To use a completely different known_hosts file, you can override CnOpts looking for ~/. ssh/known_hosts by specifying the file when instantiating.

How do I use Pysftp?

You can list the content of the directory using pysftp in Python. For that, you need your hostname, username, and password. Then you need to switch from the directory using either the cwd or chdir method and provide the remote directory as the first argument.

What is Hostkey in SFTP?

A host key is the SFTP server's public key. Ensuring the SFTP server is validated is an important aspect of the SFTP protocol. It is designed to protect against man-in-the-middle attacks where the hacker intercepts and relays an impersonated message to the other party.


2 Answers

The pysftp has some bugs regarding host key handling, as described below. It also seems that the pysftp project was abandoned. Consider using Paramiko directly instead. The pysftp is just a wrapper on top of Paramiko and it does not add anything really significant. See pysftp vs. Paramiko.

For handling of host keys in Paramiko, see:
Paramiko "Unknown Server"


If you want to keep using pysftp, do not set cnopts.hostkeys = None (as the second most upvoted answer shows), unless you do not care about security. You lose a protection against Man-in-the-middle attacks by doing so.

Use CnOpts.hostkeys (returns HostKeys) to manage trusted host keys.

cnopts = pysftp.CnOpts(knownhosts='known_hosts')  with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp: 

where the known_hosts contains a server public key(s)] in a format like:

example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB... 

If you do not want to use an external file, you can also use

from base64 import decodebytes # ...  keydata = b"""AAAAB3NzaC1yc2EAAAADAQAB...""" key = paramiko.RSAKey(data=decodebytes(keydata)) cnopts = pysftp.CnOpts() cnopts.hostkeys.add('example.com', 'ssh-rsa', key)  with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp: 

Though as of pysftp 0.2.9, this approach will issue a warning, what seems like a bug:
"Failed to load HostKeys" warning while connecting to SFTP server with pysftp


An easy way to retrieve the host key in the needed format is using OpenSSH ssh-keyscan:

$ ssh-keyscan example.com # example.com SSH-2.0-OpenSSH_5.3 example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB... 

(due to a bug in pysftp, this does not work, if the server uses non-standard port – the entry starts with [example.com]:port + beware of redirecting ssh-keyscan to a file in PowerShell)

You can also make the application do the same automatically:
Use Paramiko AutoAddPolicy with pysftp
(It will automatically add host keys of new hosts to known_hosts, but for known host keys, it will not accept a changed key)


Though for an absolute security, you should not retrieve the host key remotely, as you cannot be sure, if you are not being attacked already.

See my article Where do I get SSH host key fingerprint to authorize the server?
It's for my WinSCP SFTP client, but most information there is valid in general.


If you need to verify the host key using its fingerprint only, see Python - pysftp / paramiko - Verify host key using its fingerprint.

like image 79
Martin Prikryl Avatar answered Oct 12 '22 08:10

Martin Prikryl


One option is to disable the host key requirement:

import pysftp cnopts = pysftp.CnOpts() cnopts.hostkeys = None    with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:     sftp.put(local_path, remote_path) 

You can find more info about that here: https://stackoverflow.com/a/38355117/1060738

Important note:

By setting cnopts.hostkeys=None you'll lose the protection against Man-in-the-middle attacks by doing so. Use @martin-prikryl answer to avoid that.

like image 34
Noam Peled Avatar answered Oct 12 '22 08:10

Noam Peled