ssh and smtp server

This commit is contained in:
Roman Hergenreder 2023-09-19 14:39:11 +02:00
parent b1380967a4
commit b3cd20ca8b
5 changed files with 157 additions and 2 deletions

@ -2,7 +2,7 @@ import os
import sys import sys
__doc__ = __doc__ or "" __doc__ = __doc__ or ""
__all__ = ["util", "fileserver", "xss_handler", "rev_shell", "xp_cmdshell", "dnsserver", "sqli"] __all__ = ["util", "fileserver", "xss_handler", "rev_shell", "xp_cmdshell", "dnsserver", "sqli", "smtpserver"]
inc_dir = os.path.dirname(os.path.realpath(__file__)) inc_dir = os.path.dirname(os.path.realpath(__file__))
sys.path.append(inc_dir) sys.path.append(inc_dir)

@ -6,4 +6,4 @@ if [ $# -lt 1 ]; then
fi fi
HOST=$1 HOST=$1
gobuster dir --url="${HOST}" --wordlist="/usr/share/wordlists/SecLists/Discovery/Web-Content/raft-large-words-lowercase.txt" -b "403,404" "${@:2}" (set -x; gobuster dir --url="${HOST}" --wordlist="/usr/share/wordlists/SecLists/Discovery/Web-Content/raft-large-words-lowercase.txt" -b "403,404" "${@:2}")

40
smtpserver.py Normal file

@ -0,0 +1,40 @@
import smtpd
import email
import asyncore
import threading
class SMTPServer(smtpd.SMTPServer):
def __init__(self, addr='0.0.0.0', port=25):
super().__init__((addr, port), None)
self.listen_thread = None
self.verbose = False
self.on_message = None
self.is_running = True
def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
if self.verbose:
print(f"SMTP IN: {peer=} {mailfrom=} {rcpttos=} {len(data)} bytes, extra:", kwargs)
if self.on_message and callable(self.on_message):
mail = email.message_from_bytes(data)
self.on_message(peer, mailfrom, rcpttos, mail)
def start(self):
if self.verbose:
print(f"SMTP server running on: {self._localaddr[0]}:{self._localaddr[1]}")
try:
while self.is_running:
asyncore.loop(timeout=1, use_poll=True)
except KeyboardInterrupt:
self.close()
def start_background(self):
self.listen_thread = threading.Thread(target=self.start)
self.listen_thread.start()
return self.listen_thread
def stop(self):
self.is_running = False
self.close()
if self.listen_thread:
self.listen_thread.join()

92
sshserver.py Normal file

@ -0,0 +1,92 @@
import socket
import select
import threading
import paramiko
class ParamikoConnection(paramiko.ServerInterface):
def __init__(self, server):
self.event = threading.Event()
self.server = server
def check_channel_request(self, kind, chanid):
print("check_channel_request", kind, chanid)
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
def check_auth_password(self, username, password):
if self.server.on_ssh_login:
return self.server.on_ssh_login(username, password)
print("check_auth_password", username, password)
return paramiko.AUTH_SUCCESSFUL
class SSHServer:
def __init__(self, addr='0.0.0.0', port=22):
self.server_address = addr
self.listen_port = port
self.listen_socket = None
self.listen_thread = None
self.client_sockets = []
self.transports = []
self.verbose = True
self.on_message = None
self.is_running = True
self.private_key = None
# hooks
self.on_ssh_login = None
def load_private_key_from_file(self, path):
with open(path, "r") as f:
self.private_key = paramiko.RSAKey.from_private_key(f)
def start(self):
if self.private_key is None:
self.private_key = paramiko.RSAKey.generate(2048)
self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.listen_socket.setblocking(False)
self.listen_socket.bind((self.server_address, self.listen_port))
self.listen_socket.listen()
if self.verbose:
print(f"SSH server running on: {self.server_address}:{self.listen_port}")
try:
while self.is_running:
try:
client_socket, client_address = self.listen_socket.accept()
if self.verbose:
print("Incoming connection:", client_address)
self.client_sockets.append(client_socket)
transport = paramiko.Transport(client_socket)
transport.add_server_key(self.private_key)
paramiko_connection = ParamikoConnection(self)
transport.start_server(server=paramiko_connection)
self.transports.append(transport)
# for client_sock in self.client_sockets:
except BlockingIOError:
pass
# handle_client(client_socket, client_address)
finally:
self.listen_socket.close()
def start_background(self):
self.listen_thread = threading.Thread(target=self.start)
self.listen_thread.start()
return self.listen_thread
def close(self):
if self.listen_socket:
self.listen_socket.close()
for sock in self.client_sockets:
sock.close()
def stop(self):
self.is_running = False
self.close()
if self.listen_thread:
self.listen_thread.join()

23
util.py

@ -9,6 +9,8 @@ import string
import sys import sys
import os import os
import io import io
import json
from PIL import Image from PIL import Image
def isPortInUse(port): def isPortInUse(port):
@ -80,6 +82,27 @@ def assert_header_present(res, header, err=None):
err = f"[-] '{res.url}' did not return header: {header}" if err is None else err err = f"[-] '{res.url}' did not return header: {header}" if err is None else err
exit_with_error(res, err) exit_with_error(res, err)
def assert_not_empty(res, err=None):
if len(res.content) > 0:
return
err = f"[-] '{res.url}' did not return any data" if err is None else err
exit_with_error(res, err)
def assert_json_path(res, path, value, err=None):
assert_content_type(res, "application/json")
assert_not_empty(res)
json_data = json.loads(res.text)
for key in filter(None, path.split(".")):
json_data = json_data[key]
if json_data == value:
return
err = f"[-] '{res.url}' value at path '{path}' does not match. got={json_data} expected={value}" if err is None else err
exit_with_error(res, err)
def openServer(address, ports=None): def openServer(address, ports=None):
listenPort = None listenPort = None
retry = True retry = True