2

I am running Python 3 with the pysftp package, version 0.2.9.

The following code I have is here. I am loading the hostkey correctly as shown by the line cnopts.hostkeys.keys().

import pysftp

key_file_test = './path_to_key_file/key_file.pub'

DOWNLOAD_UAT = {
    "USERNAME": "xxxxxxxx",
    "PASSWORD": "xxxxxxxx"
}

UAT_FTP_SITE = 'sftp-test.site.com'

cnopts = pysftp.CnOpts()
cnopts.hostkeys.load(key_file_test)
cnopts.hostkeys.keys()

'''['github.com', 'XXX.XX.XXX.XXX', 'sftp-test.site.com']'''

srv = pysftp.Connection(host=UAT_SFTP_SITE, username=DOWNLOAD_UAT['USERNAME'], 
                        password=DOWNLOAD_UAT['PASSWORD'], cnopts=cnopts, port=22)

Then my error when I run the last line is

---------------------------------------------------------------------------
SSHException                              Traceback (most recent call last)
<ipython-input-82-308ec955a92e> in <module>()
      8 
      9 srv = pysftp.Connection(host=UAT_SFTP_SITE, username=DOWNLOAD_UAT['USERNAME'], 
---> 10                         password=DOWNLOAD_UAT['PASSWORD'], cnopts=cnopts, port=22)
     11 data = srv.listdir()

C:\ProgramData\Anaconda3\lib\site-packages\pysftp\__init__.py in __init__(self, host, username, private_key, password, port, private_key_pass, ciphers, log, cnopts, default_path)
    141         self._transport.use_compression(self._cnopts.compression)
    142         self._set_authentication(password, private_key, private_key_pass)
--> 143         self._transport.connect(**self._tconnect)
    144 
    145     def _set_authentication(self, password, private_key, private_key_pass):

C:\ProgramData\Anaconda3\lib\site-packages\paramiko\transport.py in connect(self, hostkey, username, password, pkey, gss_host, gss_auth, gss_kex, gss_deleg_creds)
   1139                     key.get_name(), repr(key.asbytes()))
   1140                 )
-> 1141                 raise SSHException('Bad host key from server')
   1142             self._log(DEBUG, 'Host key verified (%s)' % hostkey.get_name())
   1143 

SSHException: Bad host key from server

Does anyone know what the problem is here?

Alex F
  • 2,086
  • 4
  • 29
  • 67

1 Answers1

9

It looks like this is a known bug in pysftp. In the accepted answer here:

pysftp -- paramiko SSHException, Bad host key from server

There is example code that directly uses the parent library (paramiko) that pysftp wraps:

import paramiko
transport = paramiko.Transport(('server.com',22))
transport.connect(username='XXXXX', password='XXXXX')
sftp = paramiko.SFTPClient.from_transport(transport)
print(sftp.listdir())

EDIT:

I updated the example above to not use a private key to connect, instead to use a username/password.

The original code I posted (see edit history) will by default load all public keys from ~/.ssh/known_hosts. If you have write access to that file, that might be the easiest solution for you. But if you cannot, the Transport class has an add_server_key(key) function that would add the server identity. See doc here.

keredson
  • 3,019
  • 1
  • 17
  • 20
  • It's not true that your code loads public keys from `known_hosts`. It actually does not load any host keys. And that's why it *"works"*. Your `known_hosts` likely contains wrong host key. By using `Transport` the way you do, you bypass the problem by you completely avoiding the host key verification. Your code is susceptible to [MITM attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack). For a correct solution, see [Verify host key with pysftp](https://stackoverflow.com/q/38939454/850848) – Martin Prikryl Oct 07 '21 at 05:26