mirror of
https://github.com/aljazceru/cowrie.git
synced 2026-01-09 09:14:27 +01:00
merge sshserver.py with ssh.py
This commit is contained in:
@@ -21,12 +21,10 @@ from twisted.conch.ssh.common import NS, getNS
|
||||
import ConfigParser
|
||||
|
||||
import fs
|
||||
import sshserver
|
||||
import auth
|
||||
import connection
|
||||
import honeypot
|
||||
import protocol
|
||||
import sshserver
|
||||
import exceptions
|
||||
|
||||
class HoneyPotSSHUserAuthServer(userauth.SSHUserAuthServer):
|
||||
@@ -211,11 +209,15 @@ class HoneyPotRealm:
|
||||
else:
|
||||
raise Exception("No supported interfaces found.")
|
||||
|
||||
class HoneyPotTransport(sshserver.CowrieSSHServerTransport):
|
||||
class HoneyPotTransport(transport.SSHServerTransport):
|
||||
"""
|
||||
"""
|
||||
|
||||
def connectionMade(self):
|
||||
"""
|
||||
Called when the connection is made from the other side.
|
||||
We send our version, but wait with sending KEXINIT
|
||||
"""
|
||||
self.transportId = uuid.uuid4().hex[:8]
|
||||
self.interactors = []
|
||||
|
||||
@@ -225,16 +227,49 @@ class HoneyPotTransport(sshserver.CowrieSSHServerTransport):
|
||||
dst_ip=self.transport.getHost().host, dst_port=self.transport.getHost().port,
|
||||
sessionno=self.transport.sessionno)
|
||||
|
||||
sshserver.CowrieSSHServerTransport.connectionMade(self)
|
||||
self.transport.write('%s\r\n' % (self.ourVersionString,))
|
||||
self.currentEncryptions = transport.SSHCiphers('none', 'none', 'none', 'none')
|
||||
self.currentEncryptions.setKeys('', '', '', '', '', '')
|
||||
|
||||
def sendKexInit(self):
|
||||
# Don't send key exchange prematurely
|
||||
if not self.gotVersion:
|
||||
return
|
||||
sshserver.CowrieSSHServerTransport.sendKexInit(self)
|
||||
transport.SSHServerTransport.sendKexInit(self)
|
||||
|
||||
def dataReceived(self, data):
|
||||
sshserver.CowrieSSHServerTransport.dataReceived(self, data)
|
||||
"""
|
||||
First, check for the version string (SSH-2.0-*). After that has been
|
||||
received, this method adds data to the buffer, and pulls out any
|
||||
packets.
|
||||
|
||||
@type data: C{str}
|
||||
"""
|
||||
self.buf = self.buf + data
|
||||
if not self.gotVersion:
|
||||
if not '\n' in self.buf:
|
||||
return
|
||||
self.otherVersionString = self.buf.strip()
|
||||
if self.buf.startswith('SSH-'):
|
||||
self.gotVersion = True
|
||||
remoteVersion = self.buf.split('-')[1]
|
||||
if remoteVersion not in self.supportedVersions:
|
||||
self._unsupportedVersionReceived(remoteVersion)
|
||||
return
|
||||
i = self.buf.index('\n')
|
||||
self.buf = self.buf[i+1:]
|
||||
self.sendKexInit()
|
||||
else:
|
||||
self.transport.write('Protocol mismatch.\n')
|
||||
log.msg('Bad protocol version identification: %s' % (self.otherVersionString))
|
||||
self.transport.loseConnection()
|
||||
return
|
||||
packet = self.getPacket()
|
||||
while packet:
|
||||
messageNum = ord(packet[0])
|
||||
self.dispatchMessage(messageNum, packet[1:])
|
||||
packet = self.getPacket()
|
||||
|
||||
# later versions seem to call sendKexInit again on their own
|
||||
if twisted.version.major < 11 and \
|
||||
not self._hadVersion and self.gotVersion:
|
||||
@@ -256,7 +291,7 @@ class HoneyPotTransport(sshserver.CowrieSSHServerTransport):
|
||||
kexAlgs=kexAlgs, keyAlgs=keyAlgs, encCS=encCS, macCS=macCS,
|
||||
compCS=compCS, format='Remote SSH version: %(version)s')
|
||||
|
||||
return sshserver.CowrieSSHServerTransport.ssh_KEXINIT(self, packet)
|
||||
return transport.SSHServerTransport.ssh_KEXINIT(self, packet)
|
||||
|
||||
# this seems to be the only reliable place of catching lost connection
|
||||
def connectionLost(self, reason):
|
||||
@@ -264,9 +299,28 @@ class HoneyPotTransport(sshserver.CowrieSSHServerTransport):
|
||||
i.sessionClosed()
|
||||
if self.transport.sessionno in self.factory.sessions:
|
||||
del self.factory.sessions[self.transport.sessionno]
|
||||
sshserver.CowrieSSHServerTransport.connectionLost(self, reason)
|
||||
transport.SSHServerTransport.connectionLost(self, reason)
|
||||
log.msg(eventid='KIPP0011', format='Connection lost')
|
||||
|
||||
def sendDisconnect(self, reason, desc):
|
||||
"""
|
||||
http://kbyte.snowpenguin.org/portal/2013/04/30/kippo-protocol-mismatch-workaround/
|
||||
Workaround for the "bad packet length" error message.
|
||||
|
||||
@param reason: the reason for the disconnect. Should be one of the
|
||||
DISCONNECT_* values.
|
||||
@type reason: C{int}
|
||||
@param desc: a descrption of the reason for the disconnection.
|
||||
@type desc: C{str}
|
||||
"""
|
||||
if not 'bad packet length' in desc:
|
||||
transport.SSHServerTransport.sendDisconnect(self, reason, desc)
|
||||
else:
|
||||
self.transport.write('Packet corrupt\n')
|
||||
log.msg('[SERVER] - Disconnecting with error, code %s\nreason: %s' % (reason, desc))
|
||||
self.transport.loseConnection()
|
||||
|
||||
|
||||
class HoneyPotSSHSession(session.SSHSession):
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
# Copyright (c) 2013 Thomas Nicholson <tnnich@googlemail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The names of the author(s) may not be used to endorse or promote
|
||||
# products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
from twisted.conch.ssh import transport
|
||||
from twisted.python import log
|
||||
|
||||
class CowrieSSHServerTransport(transport.SSHServerTransport):
|
||||
def connectionMade(self):
|
||||
"""
|
||||
Called when the connection is made to the other side. We sent our
|
||||
version and the MSG_KEXINIT packet.
|
||||
"""
|
||||
self.transport.write('%s\r\n' % (self.ourVersionString,))
|
||||
self.currentEncryptions = transport.SSHCiphers('none', 'none', 'none', 'none')
|
||||
self.currentEncryptions.setKeys('', '', '', '', '', '')
|
||||
|
||||
def dataReceived(self, data):
|
||||
"""
|
||||
First, check for the version string (SSH-2.0-*). After that has been
|
||||
received, this method adds data to the buffer, and pulls out any
|
||||
packets.
|
||||
|
||||
@type data: C{str}
|
||||
"""
|
||||
self.buf = self.buf + data
|
||||
if not self.gotVersion:
|
||||
if not '\n' in self.buf:
|
||||
return
|
||||
self.otherVersionString = self.buf.strip()
|
||||
if self.buf.startswith('SSH-'):
|
||||
self.gotVersion = True
|
||||
remoteVersion = self.buf.split('-')[1]
|
||||
if remoteVersion not in self.supportedVersions:
|
||||
self._unsupportedVersionReceived(remoteVersion)
|
||||
return
|
||||
i = self.buf.index('\n')
|
||||
self.buf = self.buf[i+1:]
|
||||
self.sendKexInit()
|
||||
else:
|
||||
self.transport.write('Protocol mismatch.\n')
|
||||
log.msg('Bad protocol version identification: %s' % (self.otherVersionString))
|
||||
self.transport.loseConnection()
|
||||
return
|
||||
packet = self.getPacket()
|
||||
while packet:
|
||||
messageNum = ord(packet[0])
|
||||
self.dispatchMessage(messageNum, packet[1:])
|
||||
packet = self.getPacket()
|
||||
|
||||
def sendDisconnect(self, reason, desc):
|
||||
"""
|
||||
http://kbyte.snowpenguin.org/portal/2013/04/30/kippo-protocol-mismatch-workaround/
|
||||
Workaround for the "bad packet length" error message.
|
||||
|
||||
@param reason: the reason for the disconnect. Should be one of the
|
||||
DISCONNECT_* values.
|
||||
@type reason: C{int}
|
||||
@param desc: a descrption of the reason for the disconnection.
|
||||
@type desc: C{str}
|
||||
"""
|
||||
if not 'bad packet length' in desc:
|
||||
# With python >= 3 we can use super?
|
||||
transport.SSHServerTransport.sendDisconnect(self, reason, desc)
|
||||
else:
|
||||
self.transport.write('Protocol mismatch.\n')
|
||||
log.msg('[SERVER] - Disconnecting with error, code %s\nreason: %s' % (reason, desc))
|
||||
self.transport.loseConnection()
|
||||
|
||||
Reference in New Issue
Block a user