ssh and smtp server
This commit is contained in:
parent
b1380967a4
commit
b3cd20ca8b
@ -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
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
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
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
|
||||||
|
Loading…
Reference in New Issue
Block a user