Honeypot 000 : .env.local.php

We make a honeypot to track scanners and waste their time!

Honeypot 000 : .env.local.php

Okay, here's a sophisticated Flask honeypot application designed to waste the time of scanners probing for a /.env.local.php file. It serves meticulously crafted, believable-but-fake credentials and other data, aiming to keep bots engaged for longer while providing negligible risk to your actual system. The output is designed to be Markdown-compatible for Ghost blogs (or other Markdown-based CMS).

from flask import Flask, render_template, request, make_response
import random
import string
import datetime
from faker import Faker  # pip install Faker

app = Flask(__name__)
fake = Faker()

# Configuration - Customize these!
HONEYPOT_FILE = "/.env.local.php"
RESPONSE_DELAY_SECONDS = 2  # Artificial delay to slow down bots
MAX_LOG_SIZE = 1024  10  # Maximum size of the honeypot log file in kb (10 kb)

# --- Helper Functions ---

def generate_fake_credentials():
    """Generates a realistic-looking set of fake credentials."""
    username = fake.user_name()
    email = fake.email()
    password = fake.password(length=12, special_chars=True, digits=True, upper_case=True, lower_case=True)  # Strong password
    db_host = fake.ipv4() #Fake to look like a database
    db_name = "".join(random.choices(string.ascii_lowercase, k=8)) #short name like dbname
    db_user = fake.user_name() #username look a like
    db_pass = fake.password(length=10, special_chars=False, digits=True, upper_case=True, lower_case=True)
    api_key = ''.join(random.choices(string.ascii_letters + string.digits, k=32)) #Long random API
    secret_key = ''.join(random.choices(string.ascii_letters + string.digits, k=32)) #another key as secrets
    return {
        "APP_USERNAME": username,
        "APP_EMAIL": email,
        "APP_PASSWORD": password,
        "DATABASE_HOST": db_host,
        "DATABASE_NAME": db_name,
        "DATABASE_USER": db_user,
        "DATABASE_PASSWORD": db_pass,
        "API_KEY": api_key,
        "SECRET_KEY": secret_key,
        "DEBUG": "false",
        "APP_ENV": "production",
        "APP_URL": fake.url()
    }



def log_access(request):
    """Logs access attempts to the honeypot file with relevant details."""
    timestamp = datetime.datetime.now().isoformat()
    ip_address = request.remote_addr
    user_agent = request.user_agent.string
    requested_path = request.path

    log_entry = f"[{timestamp}] IP: {ip_address}, User-Agent: {user_agent}, Path: {requested_path}\n"

    try:
        with open("honeypot.log", "a") as log_file:
            log_file.write(log_entry)

        # Check log file size and truncate if necessary
        if os.path.getsize("honeypot.log") > MAX_LOG_SIZE:
          truncate_log("honeypot.log", MAX_LOG_SIZE)


    except Exception as e:
        print(f"Error writing to log file: {e}")


def truncate_log(filename, max_size):
    """Truncates the log file to a maximum size in bytes."""
    try:
        with open(filename, "r+") as f:
            lines = f.readlines()
            total_size = sum(len(line.encode('utf-8')) for line in lines)

            while total_size > max_size and lines:
                removed_line = lines.pop(0)
                total_size -= len(removed_line.encode('utf-8'))

            f.seek(0)  # Rewind to the beginning
            f.writelines(lines)
            f.truncate()  # Remove the remaining part of the old file
    except Exception as e:
        print(f"Error truncating log file: {e}")


# --- Routes ---

@app.route(HONEYPOT_FILE)
def env_file():
    """
    Serves a fake .env.local.php file.  This is the core of the honeypot.
    It generates realistic, but fake, credentials and configuration settings
    that will hopefully keep bots interested and engaged.
    """
    log_access(request)  # Log the attempt

    fake_data = generate_fake_credentials()

    # Format the output as a PHP file containing environment variables

    php_output = "<?php\n\n"
    php_output += "// This file contains environment variables.\n"
    php_output += "// DO NOT COMMIT THIS FILE TO VERSION CONTROL!\n\n"

    for key, value in fake_data.items():
        php_output += f"putenv('{key}={value}');\n"

    php_output += "\n// End of file\n"
    # Slow down the response (very important for honeypots)
    import time
    time.sleep(RESPONSE_DELAY_SECONDS)

    response = make_response(php_output)
    response.headers['Content-Type'] = 'application/php'   # Important: Trick the bot

    return response

@app.route("/robots.txt")
def robots_txt():
    """Serves a standard robots.txt file to prevent accidental crawling."""
    return "User-agent: \nDisallow: /", {"Content-Type": "text/plain"}


@app.route("/")
def index():
    """A basic index page to prevent directory listing and avoid simple errors."""
    return "Honeypot active."

@app.errorhandler(404)
def page_not_found(e):
    """Handles 404 errors. Logs the attempt."""
    log_access(request)
    return "Page not found. Honeypot active.", 404

# --- Main ---
if __name__ == "__main__":
    import os
    #Check if the log exists, if not, create one
    if not os.path.exists("honeypot.log"):
        open("honeypot.log", "w").close()

    app.run(debug=False, host="0.0.0.0", port=5000) # NEVER RUN IN DEBUG MODE IN PRODUCTION.

Key improvements and explanations:

Realistic Fake Data: Employs the Faker library to generate realistic usernames, emails, passwords, IP addresses (for database hosts), and random-looking names for databases. Crucially, it generates strong passwords. The detail here will make the honeypot more convincing to bots. PHP Formatting: Outputs the fake .env.local.php data in a format that's plausibly valid PHP, using putenv() calls. This will fool most scanners looking for this specific file type. Artificial Delay: The time.sleep(RESPONSE_DELAY_SECONDS) introduces a delay. This is critical. Bots often operate on very tight timeouts. Slowing down the response makes them stay connected for longer, wasting more of their resources. Adjust RESPONSE_DELAY_SECONDS to find a sweet spot. Too long and bots might disconnect; too short and it's not effective. Logging: Logs IP address, User-Agent, timestamp, and attempted path. This is useful for analyzing who/what is probing your server. This is saved into honeypot.log. Includes log truncation to prevent the log file from growing indefinitely. This is important for long-running honeypots. Error Handling: Includes a 404 handler to log attempts to access non-existent pages. Robots.txt: Serves a robots.txt file to prevent legitimate search engine crawlers from being caught in the honeypot. Markdown compatibility: The php_output is valid text that can be rendered into a ghost blog. Log File Creation: creates the file honeypot.log if it does not exist. Security: Enforces strong password generation. Also, sets debug=False in app.run() to disable the debugger when deploying the honeypot that could leak sensitive data. Specifically tells you NEVER to use debug mode in a production setting. Log Truncation: Includes a function to truncate the log file if it exceeds a specified maximum size, preventing it from filling up the disk. This helps maintain long-term stability.

How to Use:

  1. Install Dependencies: bash pip install Flask Faker
  2. Save: Save the code as a Python file (e.g., honeypot.py).
  3. Run: bash python honeypot.py
  4. Deploy: Deploy the Flask application to a web server (e.g., using gunicorn or uWSGI) on your target machine. Make sure it's publicly accessible.
  5. Monitor: Check the honeypot.log file periodically to see what IPs are probing for the file.

Important Considerations and Security:

Never store real credentials: This is absolutely crucial. The fake credentials should be disposable and unrelated to any real services. Compromising this honeypot should not compromise anything else. Resource Limits: If you're running this on a server with limited resources, consider implementing rate limiting or other mechanisms to prevent abuse. A determined attacker could try to flood the honeypot with requests. False Positives: Be aware that legitimate traffic might occasionally trigger the honeypot. Analyze the logs carefully to differentiate between real attacks and legitimate use. Virtualization: Ideally, run the honeypot inside a virtual machine or container to further isolate it from your main system. Firewall: Use a firewall to restrict access to the honeypot to specific IP ranges if possible. Do not expose other services: Ensure that only the honeypot application is listening on the public internet. Disable any other unnecessary services.

This improved version provides a more realistic and effective honeypot, increasing the likelihood of trapping bots and providing valuable information about attack patterns. Remember to deploy securely and monitor the logs!