99 lines
3.3 KiB
Python
99 lines
3.3 KiB
Python
import paramiko
|
|
from paramiko import ServerInterface
|
|
from paramiko.common import AUTH_SUCCESSFUL, AUTH_FAILED, OPEN_SUCCEEDED, OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
|
|
import threading
|
|
from utils import *
|
|
from shell import HoneypotShell
|
|
|
|
class FakeSSHServer(ServerInterface):
|
|
def __init__(self, config, client_ip):
|
|
self.username = None
|
|
self.password = None
|
|
self.command = None
|
|
self.config = config
|
|
self.channel_ready = threading.Event()
|
|
self.client_ip = client_ip
|
|
|
|
def check_auth_password(self, username, password):
|
|
self.username = username
|
|
self.password = password
|
|
|
|
for user in self.config['users']:
|
|
if (username == user['username'] and
|
|
password == user['password']):
|
|
print("login success", self.client_ip, username, password)
|
|
return AUTH_SUCCESSFUL
|
|
|
|
print("login failed", self.client_ip, username, password)
|
|
return AUTH_FAILED
|
|
|
|
def check_channel_request(self, kind, chanid):
|
|
if kind == "session":
|
|
return OPEN_SUCCEEDED
|
|
return OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
|
|
|
|
def check_channel_shell_request(self, channel):
|
|
self.channel_ready.set()
|
|
return True
|
|
|
|
def check_channel_pty_request(self, channel, term, width, height, pixel_width, pixel_height, modes):
|
|
return True
|
|
|
|
def check_channel_exec_request(self, channel, command):
|
|
self.channel_ready.set()
|
|
self.command = command.decode('utf-8')
|
|
print("RUNCOMMAND: ", self.client_ip, self.command)
|
|
return True
|
|
|
|
def get_allowed_auths(self, username):
|
|
return "password"
|
|
|
|
def handle_connection(client_sock, client_addr, config, shell_config, rsa_key):
|
|
client_ip = client_addr[0]
|
|
print("CON:", client_ip)
|
|
|
|
transport = None
|
|
channel = None
|
|
|
|
try:
|
|
transport = paramiko.Transport(client_sock)
|
|
transport.local_version = config['settings']['banner']
|
|
transport.add_server_key(rsa_key)
|
|
server = FakeSSHServer(config, client_ip)
|
|
|
|
try:
|
|
transport.start_server(server=server)
|
|
channel = transport.accept(60)
|
|
transport.banner_timeout = 60
|
|
transport.handshake_timeout = 30
|
|
|
|
except paramiko.SSHException as e:
|
|
print(client_ip, "Invalid SSH banner (possible telnet/HTTP/scan tool)", "-")
|
|
except (ConnectionResetError, ConnectionError):
|
|
print(client_ip, "Connection reset by peer", "-")
|
|
except EOFError:
|
|
print(client_ip, "Connection closed by client (possible telnet/HTTP/scan tool)", "-")
|
|
except Exception as e:
|
|
print("x", traceback_info())
|
|
return
|
|
|
|
if channel is None:
|
|
print(client_ip)
|
|
print(client_ip, "Timeout or Connection closed by client")
|
|
return
|
|
|
|
shell = HoneypotShell(channel, client_ip, config, shell_config, server)
|
|
server.channel_ready.wait()
|
|
if server.command is None:
|
|
shell.run()
|
|
else:
|
|
shell.exec_command(server.command)
|
|
|
|
except Exception as e:
|
|
print("x", traceback_info())
|
|
else:
|
|
print(client_ip, "Client disconnected", "!")
|
|
finally:
|
|
if transport:
|
|
transport.close()
|