Opened 3 years ago

Last modified 18 months ago

#7946 defect new

conch server fails when client connects with ed25519 key

Reported by: Michel Oosterhof Owned by:
Priority: normal Milestone:
Component: conch Keywords:
Cc: z3p, the0id Branch:
Author:

Description

Hello! Conch server fails when a client connects that has an ed25519 key. To reproduce run:

ssh-keygen -t ed25519 ssh conch

And the twisted.log shows:

2015-06-19 11:02:59+0000 [-] Log opened. 2015-06-19 11:02:59+0000 [-] twistd 14.0.2 (/usr/bin/python 2.7.9) starting up. 2015-06-19 11:02:59+0000 [-] reactor class: twisted.internet.epollreactor.EPollReactor. 2015-06-19 11:02:59+0000 [-] OpenSSHFactory starting on 8888 2015-06-19 11:02:59+0000 [-] Starting factory <twisted.conch.openssh_compat.factory.OpenSSHFactory instance at 0x7efbfa769c20> 2015-06-19 11:03:09+0000 [twisted.conch.openssh_compat.factory.OpenSSHFactory] disabling diffie-hellman-group-exchange because we

cannot find moduli file

2015-06-19 11:03:09+0000 [SSHServerTransport,0,127.0.0.1] kex alg, key alg: diffie-hellman-group1-sha1 ssh-rsa 2015-06-19 11:03:09+0000 [SSHServerTransport,0,127.0.0.1] outgoing: aes256-ctr hmac-sha1 none 2015-06-19 11:03:09+0000 [SSHServerTransport,0,127.0.0.1] incoming: aes256-ctr hmac-sha1 none 2015-06-19 11:03:09+0000 [SSHServerTransport,0,127.0.0.1] NEW KEYS 2015-06-19 11:03:09+0000 [SSHServerTransport,0,127.0.0.1] starting service ssh-userauth 2015-06-19 11:03:09+0000 [SSHService ssh-userauth on SSHServerTransport,0,127.0.0.1] root trying auth none 2015-06-19 11:03:09+0000 [SSHService ssh-userauth on SSHServerTransport,0,127.0.0.1] root trying auth publickey 2015-06-19 11:03:09+0000 [SSHService ssh-userauth on SSHServerTransport,0,127.0.0.1] Unhandled Error

Traceback (most recent call last):

File "/usr/lib/python2.7/dist-packages/twisted/internet/tcp.py", line 214, in doRead

return self._dataReceived(data)

File "/usr/lib/python2.7/dist-packages/twisted/internet/tcp.py", line 220, in _dataReceived

rval = self.protocol.dataReceived(data)

File "/usr/lib/python2.7/dist-packages/twisted/conch/ssh/transport.py", line 461, in dataReceived

self.dispatchMessage(messageNum, packet[1:])

File "/usr/lib/python2.7/dist-packages/twisted/conch/ssh/transport.py", line 483, in dispatchMessage

messageNum, payload)

--- <exception caught here> ---

File "/usr/lib/python2.7/dist-packages/twisted/python/log.py", line 88, in callWithLogger

return callWithContext({"system": lp}, func, *args, kw)

File "/usr/lib/python2.7/dist-packages/twisted/python/log.py", line 73, in callWithContext

return context.call({ILogContext: newCtx}, func, *args, kw)

File "/usr/lib/python2.7/dist-packages/twisted/python/context.py", line 118, in callWithContext

return self.currentContext().callWithContext(ctx, func, *args, kw)

File "/usr/lib/python2.7/dist-packages/twisted/python/context.py", line 81, in callWithContext

return func(*args,kw)

File "/usr/lib/python2.7/dist-packages/twisted/conch/ssh/service.py", line 44, in packetReceived

return f(packet)

File "/usr/lib/python2.7/dist-packages/twisted/conch/ssh/userauth.py", line 180, in ssh_USERAUTH_REQUEST

d = self.tryAuth(method, user, rest)

File "/usr/lib/python2.7/dist-packages/twisted/conch/ssh/userauth.py", line 154, in tryAuth

ret = f(data)

File "/usr/lib/python2.7/dist-packages/twisted/conch/ssh/userauth.py", line 265, in auth_publickey

pubKey = keys.Key.fromString(blob)

File "/usr/lib/python2.7/dist-packages/twisted/conch/ssh/keys.py", line 87, in fromString

raise BadKeyError('cannot guess the type of %r' % data)

twisted.conch.ssh.keys.BadKeyError: cannot guess the type of '\x00\x00\x00\x0bssh-ed25519\x00\x00\x00 \x9e\xec\x9d\xe9\x8

f\xaa\x05\x826\xe2\x83=\x00\xdb)5)\xea\xde\xec\xaf\x8b\xe0)\x0fo$Om\xa5\xb5\xb6'

Probably in tryAuth or somewhere there should be a try: to check for exceptions and fail gracefully.

Change History (8)

comment:1 Changed 3 years ago by DefaultCC Plugin

Cc: z3p added

comment:2 Changed 3 years ago by Michel Oosterhof

An example implementation is here: https://github.com/micheloosterhof/cowrie/commit/60ec0ca2805bd5ffe2ea22280424c8dabd9a32e4

(This project is a honeypot so just returns incorrect signature, Conch itself may want to return something else that fails authentication but doesn't break authentication as the current system does.

comment:3 Changed 18 months ago by Adi Roiban

here is a duplicate report #9139

comment:4 Changed 18 months ago by Adi Roiban

For the fix, this (https://github.com/twisted/twisted/blob/trunk/src/twisted/conch/ssh/userauth.py#L266) need to catch any exceptions found during Key deserialization

Here is my implementation for this... as I need some hooks (the emitEvent part)

    def auth_publickey(self, packet):
        """
        Public key authentication.  Payload::
            byte has signature
            string algorithm name
            string key data
            [string signature] (if has signature is True)

        Create a SSHPublicKey credential and verify it using our portal.
        """
        peer = self.transport.transport.getPeer()
        has_signature = ord(packet[0])
        key_algorithm, key_data, rest = getNS(packet[1:], 2)
        try:
            pubKey = Key.fromString(key_data)
        except Exception as error:
            data = {'details': str(error)}
            self.transport.emitEvent(u'30049', data=data)
            return defer.fail(UnauthorizedLogin())

        signature = has_signature and getNS(rest)[0] or None
        if has_signature:
            key_signed_data = (
                NS(self.transport.sessionID) + chr(MSG_USERAUTH_REQUEST) +
                NS(self.user) + NS(self.nextService) + NS('publickey') +
                chr(has_signature) + NS(pubKey.sshType()) + NS(key_data))
            credentials = SSHKeyCredentials(
                username=self._username,
                peer=peer,
                creator=self.transport.factory,
                key_algorithm=key_algorithm,
                key_data=key_data,
                key_signed_data=key_signed_data,
                key_signature=signature,
                )
            deferred = self.portal.login(credentials, None)
        else:
            credentials = SSHKeyCredentials(
                username=self._username,
                peer=peer,
                creator=self.transport.factory,
                key_algorithm=key_algorithm,
                key_data=key_data,
                )
            deferred = self.portal.login(credentials, None)

        deferred.addErrback(self._ebCheckKey, packet[1:])
        return deferred

comment:5 Changed 18 months ago by the0id

It looks like my ticket was a duplicate. This is the same error I'm seeing.

Adi, I don't see anything wrong with your solution, but I have a PR here for review if you want it.

comment:6 Changed 18 months ago by hawkowl

Added a review on the0id's PR.

comment:7 Changed 18 months ago by the0id

Cc: the0id added
Keywords: review added

comment:8 Changed 18 months ago by hawkowl

Keywords: review removed

Reviewed & merged PR. This ticket should now probably be related to the greater ed25519 support?

Note: See TracTickets for help on using tickets.