From efef02f6dafb1bc5876b3ac28f61d178d2f123f2 Mon Sep 17 00:00:00 2001 From: Roman Hergenreder Date: Mon, 31 May 2021 14:13:01 +0200 Subject: [PATCH] bugfixes + exploit template --- fileserver.py | 83 ++++++++++++++++++++++++++++++++++++------------ subdomainFuzz.sh | 4 +-- template.py | 49 ++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 23 deletions(-) create mode 100755 template.py diff --git a/fileserver.py b/fileserver.py index 109616f..e3ef843 100755 --- a/fileserver.py +++ b/fileserver.py @@ -1,6 +1,7 @@ #!/usr/bin/env python from http.server import BaseHTTPRequestHandler, HTTPServer +from urllib.parse import urlparse import threading import requests import sys @@ -20,37 +21,73 @@ class FileServerRequestHandler(BaseHTTPRequestHandler): def do_POST(self): self.do_GET() - def onForward(self, target): - queryStr = "" if "?" not in self.path else self.path[self.path.index("?")+1:] - if queryStr: - target += "?" if "?" not in target else "&" - target += queryStr + def onForward(self, base_path, target): + path = self.path[max(0, len(base_path)-1):] + parts = urlparse(target) + if path.startswith(parts.path): + path = path[len(parts.path):] + + target_rewrite = target + path + + # queryStr = "" if "?" not in self.path else self.path[self.path.index("?")+1:] + # if queryStr: + # target += "?" if "?" not in target else "&" + # target += queryStr + + contentLength = self.headers.get('Content-Length') + data = None + + if contentLength and int(contentLength) > 0: + data = self.rfile.read(int(contentLength)) method = self.command - res = requests.request(method, target) - return res.content, res.status_code + print(target, "=>", method, target_rewrite) + res = requests.request(method, target_rewrite, headers=self.headers, data=data) + return res.status_code, res.content, res.headers + + + def find_route(self, path): + + if path in self.server.routes: + return self.server.routes[path] + + for p, route in self.server.prefix_routes.items(): + if path.startswith(p): + return route + + def not_found(req): + return 404, b"", {} + + return not_found + + def do_OPTIONS(self): + self.do_GET() def do_GET(self): path = self.server.cleanPath(self.path) - if path in self.server.routes: - result = self.server.routes[path](self) - 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] + route = self.find_route(path) + result = route(self) - self.send_response(status_code) + blacklist_headers = ["transfer-encoding", "content-length", "content-encoding", "allow", "connection"] + 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] - for key, value in headers.items(): + self.log_request(status_code) + 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.end_headers() + if self.command.upper() == "OPTIONS": + self.send_header("Allow", "OPTIONS, GET, HEAD, POST") - if data and self.command != "HEAD": - self.wfile.write(data) - else: - self.send_response(404) - self.end_headers() + self.end_headers() + + if data and self.command.upper() not in ["HEAD","OPTION"]: + self.wfile.write(data) if path in self.server.dumpRequests: contentLength = self.headers.get('Content-Length') @@ -77,6 +114,7 @@ class HttpFileServer(HTTPServer): self.logRequests = False self.routes = { } self.dumpRequests = [] + self.prefix_routes = { } def cleanPath(self, path): @@ -101,8 +139,11 @@ class HttpFileServer(HTTPServer): def addRoute(self, path, func): self.routes[self.cleanPath(path)] = func + def addPrefixRoute(self, path, func): + self.prefix_routes[self.cleanPath(path)] = func + def forwardRequest(self, path, target): - self.addRoute(path, lambda req: req.onForward(target)) + self.addPrefixRoute(path, lambda req: req.onForward(path, target)) def enableLogging(self): self.logRequests = True diff --git a/subdomainFuzz.sh b/subdomainFuzz.sh index 7d553bf..9804c96 100755 --- a/subdomainFuzz.sh +++ b/subdomainFuzz.sh @@ -26,8 +26,8 @@ IP_ADDRESS=$(echo $output | head -n 1 | awk '{print $NF}') echo "[+] IP-Address: ${IP_ADDRESS}" echo "[ ] Retrieving default site…" -charcountDomain=$(curl -s -L "${PROTOCOL}://${DOMAIN}" -k | wc -m) -charcountIpAddress=$(curl -s -L "${PROTOCOL}://${IP_ADDRESS}" -k | wc -m) +charcountDomain=$(curl -s "${PROTOCOL}://${DOMAIN}" -k | wc -m) +charcountIpAddress=$(curl -s "${PROTOCOL}://${IP_ADDRESS}" -k | wc -m) echo "[+] Chars: ${charcountDomain} and ${charcountIpAddress}" echo "[ ] Fuzzing…" diff --git a/template.py b/template.py new file mode 100755 index 0000000..ca121b1 --- /dev/null +++ b/template.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +import sys + +def generateTemplate(baseUrl): + template = """#!/usr/bin/env python + +import requests +import base64 +import json +from bs4 import BeautifulSoup +from hackingscripts import util, fileserver +from urllib3.exceptions import InsecureRequestWarning +requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) + +BASE_URL = "%s" + +def login(username, password): + # Template method to create a session + session = requests.Session() + post_data = { "username": username, "password": password } + res = ression.post(BASE_URL + "/login", data=post_data, allow_redirects=False) + if res.status_code != 302 or "Location" not in res.headers or res.headers["Location"] != "/home": + print("Login failed") + exit() + return session + +def exploit(session, payload): + # Template method to exploit an endpoint + pass + +session = login() +exploit(session, "id") +""" % baseUrl + + return template + +if __name__ == "__main__": + + if len(sys.argv) < 2: + print("Usage: %s " % sys.argv[0]) + exit() + + url = sys.argv[1] + if "://" not in url: + url = "http://" + url + + template = generateTemplate(url) + print(template)