Skip to content

Instantly share code, notes, and snippets.

@emdnaia
Last active November 7, 2025 23:45
Show Gist options
  • Select an option

  • Save emdnaia/8d71dba96f28d29bc2a835b914450a1c to your computer and use it in GitHub Desktop.

Select an option

Save emdnaia/8d71dba96f28d29bc2a835b914450a1c to your computer and use it in GitHub Desktop.
Stored_Procedure_Honeypot

5 min POC inspired by https://x.com/IceSolst/status/1986764951940124676?s=20

# Install MariaDB
sudo dnf install mariadb-server mariadb -y

# Start and enable service
sudo systemctl start mariadb
sudo systemctl enable mariadb

# Check status
sudo systemctl status mariadb
# Login as root
sudo mysql -u root -p
-- Create database
CREATE DATABASE testdb;

-- Create test user
CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'testpass123';

-- Grant privileges
GRANT ALL PRIVILEGES ON testdb.* TO 'testuser'@'localhost';
FLUSH PRIVILEGES;

-- Switch to testdb
USE testdb;
-- Create security alerts table
CREATE TABLE security_alerts (
    alert_id INT AUTO_INCREMENT PRIMARY KEY,
    event_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    event_type VARCHAR(100),
    user_name VARCHAR(100),
    client_host VARCHAR(255),
    query_text TEXT
) ENGINE=InnoDB;
-- Honeypot 1: Get Admin Credentials
DELIMITER $$

CREATE PROCEDURE sp_get_admin_credentials()
BEGIN
    -- Log the access attempt
    INSERT INTO security_alerts (event_type, user_name, client_host)
    VALUES (
        'HONEYPOT_ADMIN_CREDS_ACCESSED',
        USER(),
        SUBSTRING_INDEX(USER(), '@', -1)
    );
    
    -- Return fake credentials
    SELECT 'admin' AS username, '**REDACTED**' AS password;
END$$

DELIMITER ;
-- Honeypot 2: Dump Passwords
DELIMITER $$

CREATE PROCEDURE sp_dump_all_passwords()
BEGIN
    INSERT INTO security_alerts (event_type, user_name, client_host)
    VALUES (
        'HONEYPOT_PASSWORD_DUMP_ATTEMPT',
        USER(),
        SUBSTRING_INDEX(USER(), '@', -1)
    );
    
    SELECT 'Access denied - Security incident logged' AS result;
END$$

DELIMITER ;
-- Honeypot 3: Backup Database Credentials
DELIMITER $$

CREATE PROCEDURE sp_get_backup_credentials()
BEGIN
    INSERT INTO security_alerts (event_type, user_name, client_host, query_text)
    VALUES (
        'HONEYPOT_BACKUP_CREDS_ACCESSED',
        USER(),
        SUBSTRING_INDEX(USER(), '@', -1),
        'Attempted to access backup credentials'
    );
    
    SELECT 
        'backup_server' AS server,
        'backup_user' AS username,
        'fake_password_123' AS password,
        '/var/backups' AS path;
END$$

DELIMITER ;
-- Grant execute permissions to testuser
GRANT EXECUTE ON PROCEDURE testdb.sp_get_admin_credentials TO 'testuser'@'localhost';
GRANT EXECUTE ON PROCEDURE testdb.sp_dump_all_passwords TO 'testuser'@'localhost';
GRANT EXECUTE ON PROCEDURE testdb.sp_get_backup_credentials TO 'testuser'@'localhost';
FLUSH PRIVILEGES;

-- Exit
EXIT;
-- Test honeypot 1
CALL sp_get_admin_credentials();

Output:

+----------+--------------+
| username | password     |
+----------+--------------+
| admin    | **REDACTED** |
+----------+--------------+
-- Test honeypot 2
CALL sp_dump_all_passwords();

Output:

+-----------------------------------------------+
| result                                        |
+-----------------------------------------------+
| Access denied - Security incident logged      |
+-----------------------------------------------+
-- Test honeypot 3
CALL sp_get_backup_credentials();

Output:

+---------------+-------------+-------------------+--------------+
| server        | username    | password          | path         |
+---------------+-------------+-------------------+--------------+
| backup_server | backup_user | fake_password_123 | /var/backups |
+---------------+-------------+-------------------+--------------+
-- View all security alerts
SELECT * FROM security_alerts;

Output:

+----------+---------------------+----------------------------------+-----------------------+-------------+
| alert_id | event_time          | event_type                       | user_name             | client_host |
+----------+---------------------+----------------------------------+-----------------------+-------------+
|        1 | 2025-11-07 10:45:23 | HONEYPOT_ADMIN_CREDS_ACCESSED    | testuser@localhost    | localhost   |
|        2 | 2025-11-07 10:45:45 | HONEYPOT_PASSWORD_DUMP_ATTEMPT   | testuser@localhost    | localhost   |
|        3 | 2025-11-07 10:46:12 | HONEYPOT_BACKUP_CREDS_ACCESSED   | testuser@localhost    | localhost   |
+----------+---------------------+----------------------------------+-----------------------+-------------+
# Create monitoring script
sudo vi /usr/local/bin/monitor_honeypot.sh
#!/bin/bash

# MariaDB configuration (uses /root/.my.cnf for authentication)
DB_NAME="testdb"
LAST_ID_FILE="/tmp/honeypot_last_id"

# Initialize last ID
if [ ! -f "$LAST_ID_FILE" ]; then
    echo "0" > "$LAST_ID_FILE"
fi

LAST_ID=$(cat "$LAST_ID_FILE")

while true; do
    # Check for new alerts (credentials from /root/.my.cnf)
    NEW_ALERTS=$(mysql -D "$DB_NAME" -sN -e \
        "SELECT CONCAT(alert_id, '|', event_time, '|', event_type, '|', user_name, '|', client_host) 
         FROM security_alerts 
         WHERE alert_id > $LAST_ID 
         ORDER BY alert_id;")
    
    if [ ! -z "$NEW_ALERTS" ]; then
        echo "🚨 HONEYPOT TRIGGERED! 🚨"
        echo "======================================"
        
        while IFS='|' read -r id time type user host; do
            echo "Alert ID: $id"
            echo "Time: $time"
            echo "Type: $type"
            echo "User: $user"
            echo "Host: $host"
            echo "--------------------------------------"
            
            # Log to syslog
            logger -t HONEYPOT "Alert: $type by $user from $host at $time"
            
            LAST_ID=$id
        done <<< "$NEW_ALERTS"
        
        echo "$LAST_ID" > "$LAST_ID_FILE"
    fi
    
    sleep 5
done
sudo chmod +x /usr/local/bin/monitor_honeypot.sh
sudo vi /etc/systemd/system/honeypot-monitor.service
[Unit]
Description=Database Honeypot Monitor
After=mariadb.service

[Service]
Type=simple
ExecStart=/usr/local/bin/monitor_honeypot.sh
Restart=always
User=root

[Install]
WantedBy=multi-user.target
# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable honeypot-monitor.service
sudo systemctl start honeypot-monitor.service
sudo systemctl status honeypot-monitor.service
  • verify
sudo mysql -u root -p

USE testdb;
SHOW PROCEDURE STATUS WHERE Db = 'testdb';

  • test
mysql -u testuser -p testdb
# Password: testpass123
  • add more logs
-- Install audit plugin
INSTALL SONAME 'server_audit';

-- Configure it
SET GLOBAL server_audit_logging=ON;
SET GLOBAL server_audit_events='CONNECT';
SET GLOBAL server_audit_file_path='/var/log/mariadb/audit.log';
  • add to etc/my.cnf.d/server.cnf
[mariadb]
plugin_load_add = server_audit
server_audit_logging = ON
server_audit_events = CONNECT,QUERY_DDL,QUERY_DML
server_audit_file_path = /var/log/mariadb/audit.log
server_audit_incl_users = testuser,root
# Create log directory first
sudo mkdir -p /var/log/mariadb
sudo chown mysql:mysql /var/log/mariadb
sudo chmod 750 /var/log/mariadb

# Create .my.cnf with credentials
cat <<EOF | sudo tee /root/.my.cnf > /dev/null
[client]
user=root
password=your_actual_mariadb_root_password
EOF

sudo chmod 600 /root/.my.cnf

# Test it works (should login without password prompt)
mysql -e "SELECT USER();"

sudo systemctl restart mariadb
  • verify
# Verify it's loaded
sudo mysql -u root -p -e "SHOW PLUGINS;" | grep server_audit
sudo mysql -u root -p -e "SHOW GLOBAL VARIABLES LIKE 'server_audit%';"

# View audit logs in real-time
sudo tail -f /var/log/mariadb/audit.log
  • less noise via
sudo mysql -u root -p -e "SET GLOBAL general_log = 'OFF';"
  • temp test
-- Enable general log temporarily for testing
SET GLOBAL general_log = 'ON';
SET GLOBAL general_log_file = '/var/log/mariadb/general.log';
CALL sp_get_admin_credentials();
CALL sp_dump_all_passwords();
CALL sp_get_backup_credentials();

-- Check alerts
SELECT * FROM security_alerts;
mysql -u testuser -p testdb -e "CALL sp_get_admin_credentials();"
mysql -u testuser -p testdb -e "CALL sp_dump_all_passwords();"

Honeytables

sudo mysql -u root -p
-- Use the existing testdb
USE testdb;

-- Create honeypot tables that look tempting
CREATE TABLE admin_passwords (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50),
    password_hash VARCHAR(255),
    last_login TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

CREATE TABLE api_keys (
    id INT AUTO_INCREMENT PRIMARY KEY,
    service VARCHAR(100),
    api_key VARCHAR(255),
    secret_key VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

CREATE TABLE backup_credentials (
    id INT AUTO_INCREMENT PRIMARY KEY,
    server VARCHAR(100),
    username VARCHAR(100),
    password VARCHAR(255),
    backup_path VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

CREATE TABLE ssh_private_keys (
    id INT AUTO_INCREMENT PRIMARY KEY,
    server VARCHAR(100),
    username VARCHAR(100),
    private_key TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

-- Insert fake but realistic-looking data
INSERT INTO admin_passwords (username, password_hash, last_login) VALUES
('admin', '$2y$10$EUIYQkbHzDdHCh8LnV5bUeZTaXQLwFWjNcZkLQ8QqCJz.qN8YsRHC', '2025-11-01 08:30:00'),
('root', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', '2025-11-02 14:22:00'),
('superadmin', '$2y$10$k7xMqYsUjDc8KlmSZ9P3qOQF7xRvJqJwM9zN8pRxTyLmWqNvUjFKa', '2025-10-28 19:45:00'),
('dbadmin', '$2y$10$fLQ8RmAHqVzLQxGBm5oNv.LxP9zRvUjXqNmWoT8pYvKlMnOpQrStu', NULL);

INSERT INTO api_keys (service, api_key, secret_key) VALUES
('stripe', 'sk_live_51HGyfhDKp2q8RxQYLN4vP9mKL', 'whsec_7kxm8nQ4pL9mKL5vP2q8RxQYLN4vP9'),
('aws', 'AKIAIOSFODNN7EXAMPLE', 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'),
('openai', 'sk-proj-AbCdEfGhIjKlMnOpQrStUvWxYz123456789', NULL),
('github', 'ghp_AbCdEfGhIjKlMnOpQrStUvWxYz123456', NULL);

INSERT INTO backup_credentials (server, username, password, backup_path) VALUES
('backup01.prod.internal', 'backup_admin', 'Backup@2024!Secure', '/mnt/backups/mysql'),
('backup02.prod.internal', 'root', 'RootBackup#2024', '/backup/postgres'),
('s3-backup.amazonaws.com', 'backup-service', 'S3Backup$ecure2024', 's3://company-backups/');

INSERT INTO ssh_private_keys (server, username, private_key) VALUES
('prod-web-01.internal', 'deploy', '-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA[FAKE_KEY_DATA_HERE]\n-----END RSA PRIVATE KEY-----'),
('prod-db-01.internal', 'root', '-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA[FAKE_KEY_DATA_HERE]\n-----END RSA PRIVATE KEY-----');

-- Grant SELECT access to testuser so they can query these tables
GRANT SELECT ON testdb.admin_passwords TO 'testuser'@'localhost';
GRANT SELECT ON testdb.api_keys TO 'testuser'@'localhost';
GRANT SELECT ON testdb.backup_credentials TO 'testuser'@'localhost';
GRANT SELECT ON testdb.ssh_private_keys TO 'testuser'@'localhost';
FLUSH PRIVILEGES;

EXIT;
  • script via sudo vi /usr/local/bin/monitor_honeypot_tables.sh
#!/bin/bash

# Configuration
AUDIT_LOG="/var/log/mariadb/audit.log"
HONEYPOT_TABLES=("admin_passwords" "api_keys" "backup_credentials" "ssh_private_keys" "database_dumps")
LAST_LINE_FILE="/tmp/honeypot_table_last_line"
DB_NAME="testdb"

# Initialize last line counter
if [ ! -f "$LAST_LINE_FILE" ]; then
    echo "0" > "$LAST_LINE_FILE"
fi

# Function to insert alert into database
log_to_database() {
    local event_type="$1"
    local user_name="$2"
    local query="$3"
    
    mysql -D "$DB_NAME" -e "INSERT INTO security_alerts (event_type, user_name, client_host, query_text) VALUES ('$event_type', '$user_name', 'localhost', '$query');" 2>/dev/null
}

# Monitor audit log
tail -n +$(cat "$LAST_LINE_FILE") -F "$AUDIT_LOG" 2>/dev/null | while read -r line; do
    # Increment line counter
    CURRENT_LINE=$(cat "$LAST_LINE_FILE")
    echo $((CURRENT_LINE + 1)) > "$LAST_LINE_FILE"
    
    # Check each honeypot table
    for table in "${HONEYPOT_TABLES[@]}"; do
        if echo "$line" | grep -iE "(SELECT|INSERT|UPDATE|DELETE).*FROM.*$table|INTO.*$table" > /dev/null; then
            echo "🚨 HONEYPOT TABLE ACCESSED! 🚨"
            echo "======================================"
            echo "Table: $table"
            echo "Time: $(date '+%Y-%m-%d %H:%M:%S')"
            
            # Extract user from audit log
            USER=$(echo "$line" | grep -oP "(?<=,')[^']+(?=')" | head -1)
            QUERY=$(echo "$line" | grep -oP "(SELECT|INSERT|UPDATE|DELETE).*" | head -1)
            
            echo "User: $USER"
            echo "Query: $QUERY"
            echo "Raw log: $line"
            echo "--------------------------------------"
            
            # Log to syslog
            logger -t HONEYPOT_TABLE "🚨 Table '$table' accessed by '$USER' - Query: $QUERY"
            
            # Log to database
            EVENT_TYPE="HONEYPOT_TABLE_${table^^}_ACCESSED"
            log_to_database "$EVENT_TYPE" "$USER" "$QUERY"
        fi
    done
done
sudo chmod +x /usr/local/bin/monitor_honeypot_tables.sh 
sudo vi /etc/systemd/system/honeypot-table-monitor.service
[Unit]
Description=Database Honeypot Table Monitor
After=mariadb.service honeypot-monitor.service

[Service]
Type=simple
ExecStart=/usr/local/bin/monitor_honeypot_tables.sh
Restart=always
User=root
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
  • test
mysql -u testuser -p testdb
# pw testpass123
-- Try to access sensitive data
SELECT * FROM admin_passwords;
SELECT * FROM api_keys;
SELECT * FROM backup_credentials;
SELECT * FROM ssh_private_keys;

-- Check if alerts were logged
SELECT * FROM security_alerts WHERE event_type LIKE 'HONEYPOT_TABLE%' ORDER BY event_time DESC;
# Terminal 1: Watch table monitor logs
sudo journalctl -u honeypot-table-monitor.service -f

# Terminal 2: Watch syslog for alerts
sudo journalctl -t HONEYPOT_TABLE -f

# Terminal 3: Watch audit log
sudo tail -f /var/log/mariadb/audit.log | grep -E "admin_passwords|api_keys|backup_credentials|ssh_private_keys"
  • more fake dbs
mysql -u root -p
-- Create a fake production database
CREATE DATABASE production_backups;

USE production_backups;

-- Create more honeypot tables
CREATE TABLE database_dumps (
    id INT AUTO_INCREMENT PRIMARY KEY,
    db_name VARCHAR(100),
    dump_file VARCHAR(255),
    dump_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO database_dumps VALUES
(1, 'customers', '/backups/customers_2025-11-07.sql.gz', '2025-11-07 02:00:00'),
(2, 'orders', '/backups/orders_2025-11-07.sql.gz', '2025-11-07 02:30:00'),
(3, 'payments', '/backups/payments_2025-11-07.sql.gz', '2025-11-07 03:00:00');

-- Grant access to testuser
GRANT ALL PRIVILEGES ON production_backups.* TO 'testuser'@'localhost';
FLUSH PRIVILEGES;

EXIT;
sudo systemctl restart honeypot-table-monitor.service
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment