2

I'm trying to upload file from s3 bucket to external SFTP server using paramiko. I've been getting BadHostKeyException: Host key for server 'XXXXXXX' does not match: got 'got_key' expected 'expect_key'. I've checked Automatically updating known_hosts file when host key changes using Paramiko but not sure that the "BadHostKeyException" is a sign of man-in-the-middle-attack. Can someone help?

#Read ssh key
key_obj = boto3.resource('s3').Object(s3_bucket, key_file)
key_str = key_obj.get()['Body'].read().decode('utf-8')
key = paramiko.RSAKey.from_private_key(io.StringIO(key_str), password='XXX') // password is private key password


#Create SSH client for SFTP upload
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.get_host_keys().add('sftp_host', 'ssh-rsa', key) 
ssh_client.connect('sftp_host', port=22, username='user_name', pkey=key)
ftp_client= ssh_client.open_sftp()
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
raghav
  • 31
  • 1
  • 6
  • Are you asking if BadHostKeyException is a sign of a man-in-the-middle attack? – Yes it is a *sign* of that. But there are other reasons why the key could have been changed (like a reinstallation of the server). – Martin Prikryl Mar 01 '21 at 09:54
  • @MartinPrikryl How do I resolve this? Could you please help me? – raghav Mar 01 '21 at 10:02
  • What do you want to help with? We cannot know if the host key change was legitimate or not. Ask the server administrator. It's not a programming question. – Martin Prikryl Mar 01 '21 at 10:04
  • I've tried with different SFTP server which is internal and it worked fine. So, not sure what is changing the host key. I'm looking for help regarding identifying why the key has been changed during connection and how should I resolve that. – raghav Mar 01 '21 at 10:09
  • What do you mean by *"key has been changed **during connection**"*? What does other SFTP server have to do with your problem with this particular SFTP server? Again, I do not think you have a programming question here. It looks like your SFTP server host key has changed and you do not know why it did happen. That's not a question we can answer here. Ask your server administrator. – Martin Prikryl Mar 01 '21 at 10:10
  • I'm getting BadHostKeyException when I call ssh_client.connect('sftp_host', port=22, username='user_name', pkey=key). The same code worked with another SFTP server which is internal to my network – raghav Mar 01 '21 at 10:12
  • @MartinPrikryl you mean to say that SFTP might be giving different key when I tried to establish connection? – raghav Mar 01 '21 at 10:16
  • I've noticed your reference to "private key". You might think that your problem has something to do with your private key. IT DOES NOT. See my answer. – Martin Prikryl Mar 01 '21 at 10:27
  • Do you need more information? – Martin Prikryl Mar 02 '21 at 10:57

2 Answers2

1

ssh_client.get_host_keys().add('sftp_host', 'ssh-rsa', key) is causing the problem here. Its actually adding my private key as host key and the same is compared with the host key from server, hence I was getting host key doesn't match. I've used key.get_base64() to get the pub key of the host and added it to known hosts which is then used during connect method to authenticate with host key generated during connect method

#Read ssh key
key_obj = boto3.resource('s3').Object(s3_bucket, key_file)
key_str = key_obj.get()['Body'].read().decode('utf-8')
key = paramiko.RSAKey.from_private_key(io.StringIO(key_str), password='XXX') // password is private key password

#Get pub key to add to known hosts
key_pub = paramiko.RSAKey(data=decodebytes(bytes(key.get_base64(), 'utf-8')), password='sftp_key_password')

#Create SSH client for SFTP upload
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.get_host_keys().add('sftp_host', 'ssh-rsa',  key_pub)
ssh_client.connect('sftp_host', port=22, username='user_name', pkey=key)
ftp_client= ssh_client.open_sftp()

#Upload gz using SFTP    
def upload_file(file_name, pandasdf, sep='|', encoding='utf-8'):
    with gzip.open(ftp_client.open(file_name, "w+", 32768), 'w+') as f:
        f.write(bytes(pandasdf.to_csv(index=False, sep=sep), encoding=encoding))

#Call upload file function
try:
    upload_file(file_name, pandasdf)
except Exception as e:
    print(e)
    print('Error while uploading file to SFTP ' + file_name)
    raise e

#Close SFTP and file resources opened
ftp_client.close()
ssh_client.close() 

raghav
  • 31
  • 1
  • 6
0

Your SSH/SFTP server host key has changed. When that happens, any decent SSH/SFTP library or client will warn you and/or prevent the connections from continuing. Change of the host key is a sign of a man-in-the-middle attack.

When this happens, you should contact your server administrator to ask whether the host key change was legitimate (e.g. the server was reinstalled) or not. If the server key has not changed, you might be under an attack.

If the key changed was legitimate, the administrator should have warned you in advance. Anyway, is this case, update the host key in your code or configuration. In your case, it's the get_host_keys().add call. In other cases, the host key might be cached in .ssh/known_hosts file.


Note that the host key has nothing to do with the "private key" you use to authenticate to your SSH server (RSAKey.from_private_key). You might want to read my article Understanding SSH key pairs.


Related question: Verify host key with pysftp.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992