From 305b166d2635cd4ddd75fb0f5bc40dd379a9da3a Mon Sep 17 00:00:00 2001 From: Roman Hergenreder Date: Fri, 1 May 2026 08:27:45 +0200 Subject: [PATCH] web-server + xss cleanup --- tools/misc/web_template.py | 18 ++--- tools/server/webserver.py | 78 +++++++++++---------- tools/server/xss_handler.py => utils/xss.py | 36 +++------- 3 files changed, 57 insertions(+), 75 deletions(-) rename tools/server/xss_handler.py => utils/xss.py (53%) diff --git a/tools/misc/web_template.py b/tools/misc/web_template.py index 63ed977..9274ccd 100755 --- a/tools/misc/web_template.py +++ b/tools/misc/web_template.py @@ -127,14 +127,14 @@ class BlindSQLiPoC(MySQLi, BlindSQLi): main_code.append("""poc = ReflectedSQLiPoC() print(poc.get_current_user()) """) - - if "http-server" in features or "file-server" in features: - partial_imports["hackingscripts.fileserver"] = ["HttpFileServer"] - main_code.append("""file_server = HttpFileServer("0.0.0.0", 3000) - file_server.enableLogging() - file_server.addRoute("/dynamic", on_request) - file_server.addFile("/static", b"static-content") - file_server.startBackground() + + if "http-server" in features or "web-server" in features or "httpserver" in features or "webserver" in features: + partial_imports["hackingscripts.tools.server.webserver"] = ["HttpServer"] + main_code.append("""http_server = HttpServer("0.0.0.0", 3000) + http_server.enable_logging() + http_server.add_route("/dynamic", on_request) + http_server.serve_data("/static", b"static-content") + http_server.start_background() """) methods.append(""" @@ -184,7 +184,7 @@ if __name__ == "__main__": "register|account: Generate an account registration method stub", "login|account: Generate an account login method stub", "sqli: Generate an template SQL-Injection class", - "http-server|file-server: Generate code for starting an in-memory http server" + "http-server|web-server: Generate code for starting an in-memory http server" ] parser.add_argument("url", type=str, help="Target URL") diff --git a/tools/server/webserver.py b/tools/server/webserver.py index 82d1996..37b62f8 100755 --- a/tools/server/webserver.py +++ b/tools/server/webserver.py @@ -8,10 +8,10 @@ import os import ssl from http.server import BaseHTTPRequestHandler, HTTPServer from urllib.parse import urlparse -from hackingscripts.utils import util -from hackingscripts.tools.server.xss_handler import generate_payload as generate_xss_payload +from hackingscripts.utils import util, xss -class FileServerRequestHandler(BaseHTTPRequestHandler): + +class HttpServerRequestHandler(BaseHTTPRequestHandler): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -22,7 +22,7 @@ class FileServerRequestHandler(BaseHTTPRequestHandler): def do_POST(self): self.do_GET() - def onForward(self, base_path, target, **kwargs): + def on_forward(self, base_path, target, **kwargs): path = self.path[max(0, len(base_path)-1):] parts = urlparse(target) if path.startswith(parts.path): @@ -83,7 +83,7 @@ class FileServerRequestHandler(BaseHTTPRequestHandler): self.end_headers() return - path = self.server.cleanPath(self.path) + path = self.server.clean_path(self.path) route = self.find_route(path) result = route(self) @@ -91,7 +91,10 @@ class FileServerRequestHandler(BaseHTTPRequestHandler): if isinstance(result, tuple): status_code = 200 if len(result) < 1 else result[0] data = b"" if len(result) < 2 else result[1] - headers = { } if len(result) < 3 else result[2] + if len(result) < 3: + headers = {} + else: + headers = {k: v for k, v in result[2].items() if k.lower() not in blacklist_headers} elif isinstance(result, int): status_code = result data = b"" @@ -105,7 +108,7 @@ class FileServerRequestHandler(BaseHTTPRequestHandler): data = data if type(data) in [bytes, bytearray] else str(data).encode() headers = {} - if path in self.server.dumpRequests: + if path in self.server.dump_requests: headers["Access-Control-Allow-Origin"] = "*" headers["Connection"] = "Close" @@ -119,8 +122,7 @@ class FileServerRequestHandler(BaseHTTPRequestHandler): self.send_response_only(status_code) for key, value in headers.items(): - if key.lower() not in blacklist_headers: - self.send_header(key, value) + self.send_header(key, value) if self.command.upper() == "OPTIONS": self.send_header("Allow", "OPTIONS, GET, HEAD, POST") @@ -132,7 +134,7 @@ class FileServerRequestHandler(BaseHTTPRequestHandler): data = data.encode() self.wfile.write(data) - if (path in self.server.dumpRequests or "/" in self.server.dumpRequests) and path != "/dummy": + if (path in self.server.dump_requests or "/" in self.server.dump_requests) and path != "/dummy": body = self.read_body() print("===== Connection from:",self.client_address[0]) @@ -150,18 +152,18 @@ class FileServerRequestHandler(BaseHTTPRequestHandler): if self.server.logRequests: super().log_message(format, *args) -class HttpFileServer(HTTPServer): +class HttpServer(HTTPServer): def __init__(self, addr, port): - super().__init__((addr, port), FileServerRequestHandler) + super().__init__((addr, port), HttpServerRequestHandler) self.ssl_context = None self.logRequests = False self.routes = { } - self.dumpRequests = [] + self.dump_requests = [] self.prefix_routes = { } self.is_running = True self.listen_thread = None - def cleanPath(self, path): + def clean_path(self, path): if "?" in path: path = path[0:path.find("?")] @@ -170,7 +172,7 @@ class HttpFileServer(HTTPServer): return path.strip() - def addFile(self, name, data, mime_type=None): + def serve_data(self, name, data, mime_type=None): assert isinstance(name, str) assert data is not None @@ -191,7 +193,7 @@ class HttpFileServer(HTTPServer): headers["Content-Type"] = mime_type # return 200 - OK and data - self.addRoute(name, lambda req: (200, data, headers)) + self.add_route(name, lambda req: (200, data, headers)) def add_file_path(self, path, name=None): def readfile(): @@ -200,7 +202,7 @@ class HttpFileServer(HTTPServer): if name is None: name = os.path.basename(path) - self.addRoute(name, lambda req: (200, readfile())) + self.add_route(name, lambda req: (200, readfile())) def load_directory(self, path, recursive=True, exclude_ext=[]): if not os.path.isdir(path): @@ -214,22 +216,22 @@ class HttpFileServer(HTTPServer): relative_path = file_path[len(path):] self.add_file_path(file_path, relative_path) - def dumpRequest(self, name): - self.dumpRequests.append(self.cleanPath(name)) + def dump_request(self, name): + self.dump_requests.append(self.clean_path(name)) - def addRoute(self, path, func): - self.routes[self.cleanPath(path)] = func + def add_route(self, path, func): + self.routes[self.clean_path(path)] = func - def addPrefixRoute(self, path, func): - self.prefix_routes[self.cleanPath(path)] = func + def add_prefix_route(self, path, func): + self.prefix_routes[self.clean_path(path)] = func - def forwardRequest(self, path, target, **kwargs): - self.addPrefixRoute(path, lambda req: req.onForward(path, target, **kwargs)) + def forward_request(self, path, target, **kwargs): + self.add_prefix_route(path, lambda req: req.on_forward(path, target, **kwargs)) - def enableLogging(self): + def enable_logging(self): self.logRequests = True - def enableSSL(self, private_key="private.key", certificate="server.crt"): + def enable_ssl(self, private_key="private.key", certificate="server.crt"): if not os.path.isfile(private_key): print("Generating private key and certificate…") @@ -242,7 +244,7 @@ class HttpFileServer(HTTPServer): self.ssl_context.load_cert_chain(certificate, private_key) self.socket = self.ssl_context.wrap_socket(self.socket, server_side=True) - def startBackground(self): + def start_background(self): self.listen_thread = threading.Thread(target=self.serve_forever) self.listen_thread.start() return self.listen_thread @@ -336,34 +338,34 @@ if __name__ == "__main__": args = parser.parse_args() - file_server = HttpFileServer(args.bind_addr, args.port) + file_server = HttpServer(args.bind_addr, args.port) ip_address = util.get_address() if args.ssl: - file_server.enableSSL(args.ssl_key, args.ssl_cert) + file_server.enable_ssl(args.ssl_key, args.ssl_cert) if args.verbose: - file_server.enableLogging() + file_server.enable_logging() if args.action == "shell": payload_type = args.payload if args.payload else "bash" shell_payload = rev_shell.generate_payload(args.payload, ip_address, 4444) - file_server.addFile("/shell", rev_shell) + file_server.serve_data("/shell", rev_shell) print("Reverse Shell URL:", file_server.get_full_url("/shell", ip_address)) elif args.action == "dump": - file_server.dumpRequest("/") + file_server.dump_request("/") print("Exfiltrate data using:", file_server.get_full_url("/", ip_address)) elif args.action == "proxy": url = "https://google.com" - file_server.forwardRequest("/proxy", url) + file_server.forward_request("/proxy", url) print("Exfiltrate data using:", file_server.get_full_url("/proxy", ip_address)) elif args.action == "xss": payload_type = args.payload if args.payload else "img" - xss = generate_xss_payload(payload_type, file_server.get_full_url("/exfiltrate", ip_address)) - file_server.addFile("/xss", xss) - file_server.dumpRequest("/exfiltrate") + xss_payload = xss.generate_payload(payload_type, file_server.get_full_url("/exfiltrate", ip_address)) + file_server.serve_data("/xss", xss_payload) + file_server.dump_request("/exfiltrate") print("Exfiltrate data using:") - print(xss) + print(xss_payload) elif args.action == "start": file_server.load_directory(".") print("Serve files in current directory using:") diff --git a/tools/server/xss_handler.py b/utils/xss.py similarity index 53% rename from tools/server/xss_handler.py rename to utils/xss.py index 17f1fda..3b70689 100755 --- a/tools/server/xss_handler.py +++ b/utils/xss.py @@ -1,9 +1,11 @@ #!/usr/bin/env python -from hackingscripts import util -from fileserver import HttpFileServer +from hackingscripts.utils import util import argparse import random +import re + +# TODO: more xss payloads, encoders, etc. def generate_payload(payload_type, url, index=None, **kwargs): payloads = [] @@ -25,13 +27,11 @@ if __name__ == "__main__": parser = argparse.ArgumentParser(description="XSS payload generator") parser.add_argument(dest="type", type=str, default=None, help="Payload type") - parser.add_argument("-p", "--port", type=int, required=False, default=None, help="Listening port") - parser.add_argument("-a", "--addr", type=str, required=False, default=util.get_address(), help="Listening address") + parser.add_argument("-u", "--url", dest="url", type=str, default="http://"+util.get_address(), help="XSS Base URL") args, extra = parser.parse_known_args() - listen_port = args.port payload_type = args.type.lower() - local_address = args.addr + url = args.url extra_args = {} for entry in extra: @@ -42,30 +42,10 @@ if __name__ == "__main__": key, value = match.groups() extra_args[key] = value - # choose random port - if listen_port is None: - listen_port = random.randint(10000,65535) - while util.is_port_in_use(listen_port): - listen_port = random.randint(10000,65535) - - http_server = HttpFileServer(local_address, listen_port) - payload_type = args.type.lower() - url = http_server.get_full_url("/", util.get_address()) payload = generate_payload(payload_type, url, **extra_args) if payload is None: - print("Unknown payload type: %s" % payload_type) + print("Unknown payload type", payload_type) # print("Supported types: ") exit(1) - print(f"---PAYLOAD---\n{payload}\n---PAYLOAD---\n") - - headers = { - "Access-Control-Allow-Origin": "*", - "Access-Control-Allow-Methods": "GET, POST, OPTIONS" - } - - http_server.addRoute("/", lambda req: (201, b"", headers)) - http_server.dumpRequest("/") - http_server.serve_forever() - - + print(payload) \ No newline at end of file