diff --git a/src/handler.py b/src/handler.py index 9d8abe2..ac7ca22 100644 --- a/src/handler.py +++ b/src/handler.py @@ -3,6 +3,7 @@ import logging import random import time +from datetime import datetime from http.server import BaseHTTPRequestHandler from typing import Optional, List @@ -25,6 +26,7 @@ class Handler(BaseHTTPRequestHandler): counter: int = 0 app_logger: logging.Logger = None access_logger: logging.Logger = None + credential_logger: logging.Logger = None def _get_client_ip(self) -> str: """Extract client IP address from request, checking proxy headers first""" @@ -213,6 +215,19 @@ class Handler(BaseHTTPRequestHandler): self.access_logger.warning(f"[POST DATA] {post_data[:200]}") + # Parse and log credentials + username, password = self.tracker.parse_credentials(post_data) + if username or password: + # Log to dedicated credentials.log file + timestamp = datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ") + credential_line = f"{timestamp}|{client_ip}|{username or 'N/A'}|{password or 'N/A'}|{self.path}" + self.credential_logger.info(credential_line) + + # Also record in tracker for dashboard + self.tracker.record_credential_attempt(client_ip, self.path, username or 'N/A', password or 'N/A') + + self.access_logger.warning(f"[CREDENTIALS CAPTURED] {client_ip} - Username: {username or 'N/A'} - Path: {self.path}") + # send the post data (body) to the record_access function so the post data can be used to detect suspicious things. self.tracker.record_access(client_ip, self.path, user_agent, post_data) diff --git a/src/logger.py b/src/logger.py index 68b8278..9f09236 100644 --- a/src/logger.py +++ b/src/logger.py @@ -77,6 +77,22 @@ class LoggerManager: access_stream_handler.setFormatter(log_format) self._access_logger.addHandler(access_stream_handler) + # Setup credential logger (special format, no stream handler) + self._credential_logger = logging.getLogger("krawl.credentials") + self._credential_logger.setLevel(logging.INFO) + self._credential_logger.handlers.clear() + + # Credential logger uses a simple format: timestamp|ip|username|password|path + credential_format = logging.Formatter("%(message)s") + + credential_file_handler = RotatingFileHandler( + os.path.join(log_dir, "credentials.log"), + maxBytes=max_bytes, + backupCount=backup_count + ) + credential_file_handler.setFormatter(credential_format) + self._credential_logger.addHandler(credential_file_handler) + self._initialized = True @property @@ -93,6 +109,13 @@ class LoggerManager: self.initialize() return self._access_logger + @property + def credentials(self) -> logging.Logger: + """Get the credentials logger.""" + if not self._initialized: + self.initialize() + return self._credential_logger + # Module-level singleton instance _logger_manager = LoggerManager() @@ -108,6 +131,11 @@ def get_access_logger() -> logging.Logger: return _logger_manager.access +def get_credential_logger() -> logging.Logger: + """Get the credential logger instance.""" + return _logger_manager.credentials + + def initialize_logging(log_dir: str = "logs") -> None: """Initialize the logging system.""" _logger_manager.initialize(log_dir) diff --git a/src/server.py b/src/server.py index 861e9f2..fd8f7d2 100644 --- a/src/server.py +++ b/src/server.py @@ -11,7 +11,7 @@ from http.server import HTTPServer from config import Config from tracker import AccessTracker from handler import Handler -from logger import initialize_logging, get_app_logger, get_access_logger +from logger import initialize_logging, get_app_logger, get_access_logger, get_credential_logger def print_usage(): @@ -45,6 +45,7 @@ def main(): initialize_logging() app_logger = get_app_logger() access_logger = get_access_logger() + credential_logger = get_credential_logger() config = Config.from_env() @@ -55,6 +56,7 @@ def main(): Handler.counter = config.canary_token_tries Handler.app_logger = app_logger Handler.access_logger = access_logger + Handler.credential_logger = credential_logger if len(sys.argv) == 2: try: diff --git a/src/templates/dashboard_template.py b/src/templates/dashboard_template.py index 3f5524d..a267278 100644 --- a/src/templates/dashboard_template.py +++ b/src/templates/dashboard_template.py @@ -45,6 +45,12 @@ def generate_dashboard(stats: dict) -> str: for log in stats.get('attack_types', [])[-10:] ]) or '
| IP Address | +Username | +Password | +Path | +Time | +
|---|