Automated Security Operations with Safeline WAF (Part 1)
Carrie
Posted on October 17, 2024
This article is originally written by a SafeLine user: 爱吃麦当劳.
Disclaimer
This tutorial is prepared for legitimate educational purposes only. It is strictly prohibited to use it for any illegal activities or commercial purposes. Before using this tutorial, ensure that your actions comply with local laws and regulations.
Introduction
I use the free edition of Safeline WAF(https://waf.chaitin.com/), but many features are restricted. Therefore, I began to automate the security operations.
Mapping Database Ports
#!/bin/bash
# Run the install/update script
bash -c "$(curl -fsSLk https://waf-ce.chaitin.cn/release/latest/upgrade.sh)"
# Enter the /data/safeline directory
cd /data/safeline || { echo "/data/safeline not found!"; exit 1; }
# Check if compose.yaml exists and back it up
if [ -f compose.yaml ]; then
echo "Backing up the current compose.yaml"
cp compose.yaml compose.yaml.bak
else
echo "compose.yaml not found in /data/safeline!"
exit 1
fi
# Check if port mapping already exists
if grep -q "5433:5432" compose.yaml; then
echo "PostgreSQL port mapping already exists."
else
# Use sed to insert ports field into the postgres service
sed -i '/container_name: safeline-pg/a\ ports:\n - 5433:5432' compose.yaml
echo "PostgreSQL port mapping added to 5433:5432."
fi
# Restart the containers to apply changes
docker compose down --remove-orphans && docker compose up -d
echo "Containers restarted with the updated compose.yaml"
This script is useful for remapping the database ports each time an update is done.
Extracting Alert Logs
Use cat /data/safeline/.env | grep POSTGRES_PASSWORD | tail -n 1 | awk -F '=' '{print $2}'
to find the database password.
Then, write the following code into /var/scripts/.pgpass
, and set its permissions to 600:
localhost:5433:safeline-ce:safeline-ce:abcd # Replace 'abcd' with the password obtained in the previous step
#!/bin/bash
# Set the PGPASSFILE environment variable
export PGPASSFILE=/var/scripts/.pgpass
# PostgreSQL connection information
PG_HOST="localhost"
PORT="5433"
DATABASE="safeline-ce"
USERNAME="safeline-ce"
HOSTNAME=$(hostname)
PROGRAM_NAME="safeline-ce"
# Get the ID of the last WAF attack event log
LAST_ID=$(psql -h $PG_HOST -p $PORT -U $USERNAME -d $DATABASE -t -P footer=off -c "SELECT id FROM PUBLIC.MGT_DETECT_LOG_BASIC ORDER BY id desc limit 1")
while true; do
# Get the latest WAF attack event log from the PostgreSQL database
raw_log=$(psql -h $PG_HOST -p $PORT -U $USERNAME -d $DATABASE -t -P footer=off -c "SELECT TO_CHAR(to_timestamp(timestamp) AT TIME ZONE 'Asia/Shanghai', 'YYYY-MM-DD HH24:MI:SS'), CONCAT(PROVINCE, CITY) AS SRC_CITY, SRC_IP, CONCAT(HOST, ':', DST_PORT) AS HOST,url_path,rule_id,id FROM PUBLIC.MGT_DETECT_LOG_BASIC where id > '$LAST_ID' ORDER BY id asc limit 1")
# Check SQL query results, if new logs are generated, rewrite the SQL query results as syslog logs, and record them in /var/log/waf_alert/waf_alert.log
if [ -n "$raw_log" ]; then
ALERT_TIME=$(echo "$raw_log" | awk -F ' \\| ' '{print $1}')
SRC_CITY=$(echo "$raw_log" | awk -F ' \\| ' '{print $2}')
SRC_IP=$(echo "$raw_log" | awk -F ' \\| ' '{print $3}')
DST_HOST=$(echo "$raw_log" | awk -F ' \\| ' '{print $4}')
URL=$(echo "$raw_log" | awk -F ' \\| ' '{print $5}')
RULE_ID=$(echo "$raw_log" | awk -F ' \\| ' '{print $6}')
EVENT_ID=$(echo "$raw_log" | awk -F ' \\| ' '{print $7}')
syslog="src_city:$SRC_CITY, src_ip:$SRC_IP, dst_host:$DST_HOST, url:$URL, rule_id:$RULE_ID, log_id:$EVENT_ID"
echo $ALERT_TIME $HOSTNAME $PROGRAM_NAME: $syslog >> /var/log/waf_alert/waf_alert.log
# Update the last processed event ID
LAST_ID=$(($LAST_ID+1))
fi
sleep 3
done
This script extracts alert logs to /var/log/waf_alert/waf_alert.log
. Before executing the log extraction script, install postgresql-client
using apt install postgresql-client
.
Run it in the background or write it into the systemctl startup script: nohup /var/scripts/waf_log.sh > /dev/null 2>&1 &
Monitoring Log File Changes
To monitor log file changes and trigger alert scripts, install inotify-tools
on Linux. The inotifywait
command can monitor file modification events and trigger a command when a change is detected.
Install inotify-tools
apt update
apt install inotify-tools
Use inotify-tools
Create a monitor.sh script with the following content:
#!/bin/bash
# Path to the log file to monitor
LOG_FILE="/var/log/waf_alert/waf_alert.log"
# Command to execute when log file changes
COMMAND_TO_EXECUTE="/var/scripts/Log_Push_linux_amd64" # Here, execute DingTalk notification
# Use inotifywait to continuously monitor the log file for modifications
inotifywait -m -e modify "$LOG_FILE" | while read path action file; do
echo "Detected $action on $file. Executing command..."
# Execute the specified command
$COMMAND_TO_EXECUTE
done
Run this script in the background, or set it as a startup item.
Implementing DingTalk Push Notifications
Here I use Golang to achieve this, which can push notifications to DingTalk.
Here is the source code: https://github.com/Fiary-Tale/Log_Push
Result
Autostart on Boot
Create a waf_monitor.service file:
[Unit]
Description=WAF Log Monitor Service
After=network.target
[Service]
Type=simple
ExecStart=/bin/bash /var/scripts/waf_log.sh
ExecStartPost=/bin/bash /var/scripts/monitor.sh
Restart=on-failure
[Install]
WantedBy=multi-user.target
Then execute the following commands:
systemctl daemon-reload # Reload systemd configuration
systemctl enable waf_monitor.service # Enable autostart on boot
systemctl start waf_monitor.service # Start the service
Posted on October 17, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.