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();"
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