web-server + xss cleanup
This commit is contained in:
@@ -128,13 +128,13 @@ class BlindSQLiPoC(MySQLi, BlindSQLi):
|
|||||||
print(poc.get_current_user())
|
print(poc.get_current_user())
|
||||||
""")
|
""")
|
||||||
|
|
||||||
if "http-server" in features or "file-server" in features:
|
if "http-server" in features or "web-server" in features or "httpserver" in features or "webserver" in features:
|
||||||
partial_imports["hackingscripts.fileserver"] = ["HttpFileServer"]
|
partial_imports["hackingscripts.tools.server.webserver"] = ["HttpServer"]
|
||||||
main_code.append("""file_server = HttpFileServer("0.0.0.0", 3000)
|
main_code.append("""http_server = HttpServer("0.0.0.0", 3000)
|
||||||
file_server.enableLogging()
|
http_server.enable_logging()
|
||||||
file_server.addRoute("/dynamic", on_request)
|
http_server.add_route("/dynamic", on_request)
|
||||||
file_server.addFile("/static", b"static-content")
|
http_server.serve_data("/static", b"static-content")
|
||||||
file_server.startBackground()
|
http_server.start_background()
|
||||||
""")
|
""")
|
||||||
|
|
||||||
methods.append("""
|
methods.append("""
|
||||||
@@ -184,7 +184,7 @@ if __name__ == "__main__":
|
|||||||
"register|account: Generate an account registration method stub",
|
"register|account: Generate an account registration method stub",
|
||||||
"login|account: Generate an account login method stub",
|
"login|account: Generate an account login method stub",
|
||||||
"sqli: Generate an template SQL-Injection class",
|
"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")
|
parser.add_argument("url", type=str, help="Target URL")
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import os
|
|||||||
import ssl
|
import ssl
|
||||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
from hackingscripts.utils import util
|
from hackingscripts.utils import util, xss
|
||||||
from hackingscripts.tools.server.xss_handler import generate_payload as generate_xss_payload
|
|
||||||
|
|
||||||
class FileServerRequestHandler(BaseHTTPRequestHandler):
|
|
||||||
|
class HttpServerRequestHandler(BaseHTTPRequestHandler):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
@@ -22,7 +22,7 @@ class FileServerRequestHandler(BaseHTTPRequestHandler):
|
|||||||
def do_POST(self):
|
def do_POST(self):
|
||||||
self.do_GET()
|
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):]
|
path = self.path[max(0, len(base_path)-1):]
|
||||||
parts = urlparse(target)
|
parts = urlparse(target)
|
||||||
if path.startswith(parts.path):
|
if path.startswith(parts.path):
|
||||||
@@ -83,7 +83,7 @@ class FileServerRequestHandler(BaseHTTPRequestHandler):
|
|||||||
self.end_headers()
|
self.end_headers()
|
||||||
return
|
return
|
||||||
|
|
||||||
path = self.server.cleanPath(self.path)
|
path = self.server.clean_path(self.path)
|
||||||
route = self.find_route(path)
|
route = self.find_route(path)
|
||||||
result = route(self)
|
result = route(self)
|
||||||
|
|
||||||
@@ -91,7 +91,10 @@ class FileServerRequestHandler(BaseHTTPRequestHandler):
|
|||||||
if isinstance(result, tuple):
|
if isinstance(result, tuple):
|
||||||
status_code = 200 if len(result) < 1 else result[0]
|
status_code = 200 if len(result) < 1 else result[0]
|
||||||
data = b"" if len(result) < 2 else result[1]
|
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):
|
elif isinstance(result, int):
|
||||||
status_code = result
|
status_code = result
|
||||||
data = b""
|
data = b""
|
||||||
@@ -105,7 +108,7 @@ class FileServerRequestHandler(BaseHTTPRequestHandler):
|
|||||||
data = data if type(data) in [bytes, bytearray] else str(data).encode()
|
data = data if type(data) in [bytes, bytearray] else str(data).encode()
|
||||||
headers = {}
|
headers = {}
|
||||||
|
|
||||||
if path in self.server.dumpRequests:
|
if path in self.server.dump_requests:
|
||||||
headers["Access-Control-Allow-Origin"] = "*"
|
headers["Access-Control-Allow-Origin"] = "*"
|
||||||
|
|
||||||
headers["Connection"] = "Close"
|
headers["Connection"] = "Close"
|
||||||
@@ -119,8 +122,7 @@ class FileServerRequestHandler(BaseHTTPRequestHandler):
|
|||||||
self.send_response_only(status_code)
|
self.send_response_only(status_code)
|
||||||
|
|
||||||
for key, value in headers.items():
|
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":
|
if self.command.upper() == "OPTIONS":
|
||||||
self.send_header("Allow", "OPTIONS, GET, HEAD, POST")
|
self.send_header("Allow", "OPTIONS, GET, HEAD, POST")
|
||||||
@@ -132,7 +134,7 @@ class FileServerRequestHandler(BaseHTTPRequestHandler):
|
|||||||
data = data.encode()
|
data = data.encode()
|
||||||
self.wfile.write(data)
|
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()
|
body = self.read_body()
|
||||||
|
|
||||||
print("===== Connection from:",self.client_address[0])
|
print("===== Connection from:",self.client_address[0])
|
||||||
@@ -150,18 +152,18 @@ class FileServerRequestHandler(BaseHTTPRequestHandler):
|
|||||||
if self.server.logRequests:
|
if self.server.logRequests:
|
||||||
super().log_message(format, *args)
|
super().log_message(format, *args)
|
||||||
|
|
||||||
class HttpFileServer(HTTPServer):
|
class HttpServer(HTTPServer):
|
||||||
def __init__(self, addr, port):
|
def __init__(self, addr, port):
|
||||||
super().__init__((addr, port), FileServerRequestHandler)
|
super().__init__((addr, port), HttpServerRequestHandler)
|
||||||
self.ssl_context = None
|
self.ssl_context = None
|
||||||
self.logRequests = False
|
self.logRequests = False
|
||||||
self.routes = { }
|
self.routes = { }
|
||||||
self.dumpRequests = []
|
self.dump_requests = []
|
||||||
self.prefix_routes = { }
|
self.prefix_routes = { }
|
||||||
self.is_running = True
|
self.is_running = True
|
||||||
self.listen_thread = None
|
self.listen_thread = None
|
||||||
|
|
||||||
def cleanPath(self, path):
|
def clean_path(self, path):
|
||||||
if "?" in path:
|
if "?" in path:
|
||||||
path = path[0:path.find("?")]
|
path = path[0:path.find("?")]
|
||||||
|
|
||||||
@@ -170,7 +172,7 @@ class HttpFileServer(HTTPServer):
|
|||||||
|
|
||||||
return path.strip()
|
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 isinstance(name, str)
|
||||||
assert data is not None
|
assert data is not None
|
||||||
@@ -191,7 +193,7 @@ class HttpFileServer(HTTPServer):
|
|||||||
headers["Content-Type"] = mime_type
|
headers["Content-Type"] = mime_type
|
||||||
|
|
||||||
# return 200 - OK and data
|
# 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 add_file_path(self, path, name=None):
|
||||||
def readfile():
|
def readfile():
|
||||||
@@ -200,7 +202,7 @@ class HttpFileServer(HTTPServer):
|
|||||||
|
|
||||||
if name is None:
|
if name is None:
|
||||||
name = os.path.basename(path)
|
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=[]):
|
def load_directory(self, path, recursive=True, exclude_ext=[]):
|
||||||
if not os.path.isdir(path):
|
if not os.path.isdir(path):
|
||||||
@@ -214,22 +216,22 @@ class HttpFileServer(HTTPServer):
|
|||||||
relative_path = file_path[len(path):]
|
relative_path = file_path[len(path):]
|
||||||
self.add_file_path(file_path, relative_path)
|
self.add_file_path(file_path, relative_path)
|
||||||
|
|
||||||
def dumpRequest(self, name):
|
def dump_request(self, name):
|
||||||
self.dumpRequests.append(self.cleanPath(name))
|
self.dump_requests.append(self.clean_path(name))
|
||||||
|
|
||||||
def addRoute(self, path, func):
|
def add_route(self, path, func):
|
||||||
self.routes[self.cleanPath(path)] = func
|
self.routes[self.clean_path(path)] = func
|
||||||
|
|
||||||
def addPrefixRoute(self, path, func):
|
def add_prefix_route(self, path, func):
|
||||||
self.prefix_routes[self.cleanPath(path)] = func
|
self.prefix_routes[self.clean_path(path)] = func
|
||||||
|
|
||||||
def forwardRequest(self, path, target, **kwargs):
|
def forward_request(self, path, target, **kwargs):
|
||||||
self.addPrefixRoute(path, lambda req: req.onForward(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
|
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):
|
if not os.path.isfile(private_key):
|
||||||
print("Generating private key and certificate…")
|
print("Generating private key and certificate…")
|
||||||
@@ -242,7 +244,7 @@ class HttpFileServer(HTTPServer):
|
|||||||
self.ssl_context.load_cert_chain(certificate, private_key)
|
self.ssl_context.load_cert_chain(certificate, private_key)
|
||||||
self.socket = self.ssl_context.wrap_socket(self.socket, server_side=True)
|
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 = threading.Thread(target=self.serve_forever)
|
||||||
self.listen_thread.start()
|
self.listen_thread.start()
|
||||||
return self.listen_thread
|
return self.listen_thread
|
||||||
@@ -336,34 +338,34 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
args = parser.parse_args()
|
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()
|
ip_address = util.get_address()
|
||||||
|
|
||||||
if args.ssl:
|
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:
|
if args.verbose:
|
||||||
file_server.enableLogging()
|
file_server.enable_logging()
|
||||||
|
|
||||||
if args.action == "shell":
|
if args.action == "shell":
|
||||||
payload_type = args.payload if args.payload else "bash"
|
payload_type = args.payload if args.payload else "bash"
|
||||||
shell_payload = rev_shell.generate_payload(args.payload, ip_address, 4444)
|
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))
|
print("Reverse Shell URL:", file_server.get_full_url("/shell", ip_address))
|
||||||
elif args.action == "dump":
|
elif args.action == "dump":
|
||||||
file_server.dumpRequest("/")
|
file_server.dump_request("/")
|
||||||
print("Exfiltrate data using:", file_server.get_full_url("/", ip_address))
|
print("Exfiltrate data using:", file_server.get_full_url("/", ip_address))
|
||||||
elif args.action == "proxy":
|
elif args.action == "proxy":
|
||||||
url = "https://google.com"
|
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))
|
print("Exfiltrate data using:", file_server.get_full_url("/proxy", ip_address))
|
||||||
elif args.action == "xss":
|
elif args.action == "xss":
|
||||||
payload_type = args.payload if args.payload else "img"
|
payload_type = args.payload if args.payload else "img"
|
||||||
xss = generate_xss_payload(payload_type, file_server.get_full_url("/exfiltrate", ip_address))
|
xss_payload = xss.generate_payload(payload_type, file_server.get_full_url("/exfiltrate", ip_address))
|
||||||
file_server.addFile("/xss", xss)
|
file_server.serve_data("/xss", xss_payload)
|
||||||
file_server.dumpRequest("/exfiltrate")
|
file_server.dump_request("/exfiltrate")
|
||||||
print("Exfiltrate data using:")
|
print("Exfiltrate data using:")
|
||||||
print(xss)
|
print(xss_payload)
|
||||||
elif args.action == "start":
|
elif args.action == "start":
|
||||||
file_server.load_directory(".")
|
file_server.load_directory(".")
|
||||||
print("Serve files in current directory using:")
|
print("Serve files in current directory using:")
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from hackingscripts import util
|
from hackingscripts.utils import util
|
||||||
from fileserver import HttpFileServer
|
|
||||||
import argparse
|
import argparse
|
||||||
import random
|
import random
|
||||||
|
import re
|
||||||
|
|
||||||
|
# TODO: more xss payloads, encoders, etc.
|
||||||
|
|
||||||
def generate_payload(payload_type, url, index=None, **kwargs):
|
def generate_payload(payload_type, url, index=None, **kwargs):
|
||||||
payloads = []
|
payloads = []
|
||||||
@@ -25,13 +27,11 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
parser = argparse.ArgumentParser(description="XSS payload generator")
|
parser = argparse.ArgumentParser(description="XSS payload generator")
|
||||||
parser.add_argument(dest="type", type=str, default=None, help="Payload type")
|
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("-u", "--url", dest="url", type=str, default="http://"+util.get_address(), help="XSS Base URL")
|
||||||
parser.add_argument("-a", "--addr", type=str, required=False, default=util.get_address(), help="Listening address")
|
|
||||||
args, extra = parser.parse_known_args()
|
args, extra = parser.parse_known_args()
|
||||||
|
|
||||||
listen_port = args.port
|
|
||||||
payload_type = args.type.lower()
|
payload_type = args.type.lower()
|
||||||
local_address = args.addr
|
url = args.url
|
||||||
extra_args = {}
|
extra_args = {}
|
||||||
|
|
||||||
for entry in extra:
|
for entry in extra:
|
||||||
@@ -42,30 +42,10 @@ if __name__ == "__main__":
|
|||||||
key, value = match.groups()
|
key, value = match.groups()
|
||||||
extra_args[key] = value
|
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)
|
payload = generate_payload(payload_type, url, **extra_args)
|
||||||
if payload is None:
|
if payload is None:
|
||||||
print("Unknown payload type: %s" % payload_type)
|
print("Unknown payload type", payload_type)
|
||||||
# print("Supported types: ")
|
# print("Supported types: ")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
print(f"---PAYLOAD---\n{payload}\n---PAYLOAD---\n")
|
print(payload)
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user