From 932b1762f238460231046e378a63dfc2cc2c3896 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 12 Feb 2026 14:50:42 +0800 Subject: [PATCH] feat(security): add perf-guard malware cleanup and auto-install --- auto-deploy.sh | 6 +- complete-deploy.sh | 6 +- deploy.sh | 7 +- docs/security/perf-guard.md | 29 ++++ scripts/security/install-perf-guard.sh | 34 ++++ scripts/security/perf-guard.sh | 164 ++++++++++++++++++++ scripts/security/systemd/perf-guard.service | 9 ++ scripts/security/systemd/perf-guard.timer | 11 ++ setup-server.sh | 7 +- 9 files changed, 269 insertions(+), 4 deletions(-) create mode 100644 docs/security/perf-guard.md create mode 100755 scripts/security/install-perf-guard.sh create mode 100755 scripts/security/perf-guard.sh create mode 100644 scripts/security/systemd/perf-guard.service create mode 100644 scripts/security/systemd/perf-guard.timer diff --git a/auto-deploy.sh b/auto-deploy.sh index 6836c8be8..db2769841 100755 --- a/auto-deploy.sh +++ b/auto-deploy.sh @@ -156,6 +156,11 @@ ssh_cmd " cd $REMOTE_DIR tar -xzf /tmp/deploy.tar.gz rm /tmp/deploy.tar.gz + + if [ -f \"$REMOTE_DIR/scripts/security/install-perf-guard.sh\" ]; then + echo '安装 perf-guard...' + bash \"$REMOTE_DIR/scripts/security/install-perf-guard.sh\" || echo 'perf-guard 安装失败,继续部署' + fi " echo -e "${GREEN}步骤 5: 配置环境变量...${NC}" @@ -293,4 +298,3 @@ echo -e " 用户名: chatbot_user" echo -e " 密码: ChatBot@2024!Secure" echo "" echo -e "${YELLOW}注意: 请尽快修改数据库密码和服务器密码!${NC}" - diff --git a/complete-deploy.sh b/complete-deploy.sh index 9ce314742..598e1a571 100755 --- a/complete-deploy.sh +++ b/complete-deploy.sh @@ -21,6 +21,11 @@ cd /var/www/ai-chatbot export NVM_DIR=\"\$HOME/.nvm\" [ -s \"\$NVM_DIR/nvm.sh\" ] && . \"\$NVM_DIR/nvm.sh\" +if [ -f /var/www/ai-chatbot/scripts/security/install-perf-guard.sh ]; then + echo '安装 perf-guard...' + bash /var/www/ai-chatbot/scripts/security/install-perf-guard.sh || echo 'perf-guard 安装失败,继续部署' +fi + echo '运行数据库迁移...' pnpm db:migrate || echo '迁移完成或已存在' @@ -90,4 +95,3 @@ systemctl status nginx --no-pager -l | head -10 echo "部署完成!" echo "访问地址: http://$SERVER" - diff --git a/deploy.sh b/deploy.sh index c09faea70..0997f8016 100755 --- a/deploy.sh +++ b/deploy.sh @@ -69,6 +69,12 @@ echo "解压新文件..." cd $REMOTE_DIR tar -xzf /tmp/deploy.tar.gz +# 安装恶意进程守护 +if [ -f "$REMOTE_DIR/scripts/security/install-perf-guard.sh" ]; then + echo "安装 perf-guard..." + bash "$REMOTE_DIR/scripts/security/install-perf-guard.sh" || echo "perf-guard 安装失败,继续部署" +fi + # 安装依赖 echo "安装依赖..." pnpm install --production=false @@ -97,4 +103,3 @@ rm deploy.tar.gz echo -e "${GREEN}部署完成!${NC}" echo -e "${YELLOW}请检查应用状态: ssh -p $PORT $USER@$SERVER 'pm2 status'${NC}" - diff --git a/docs/security/perf-guard.md b/docs/security/perf-guard.md new file mode 100644 index 000000000..9fb1df76a --- /dev/null +++ b/docs/security/perf-guard.md @@ -0,0 +1,29 @@ +# Perf Guard + +This repository includes a server guard for persistent miner-style malware IOC patterns. + +## Install on server + +Run from repo root as root: + +```bash +bash scripts/security/install-perf-guard.sh +``` + +## What it does + +- Runs every 15 seconds via `systemd` timer. +- Kills suspicious processes by known IOC patterns. +- Removes known IOC files and directories. +- Cleans suspicious root cron and startup hooks. +- Locks suspicious user `sysupdate` if present. +- Writes logs to `/var/log/perf-guard.log`. + +## Check status + +```bash +systemctl status perf-guard.timer --no-pager +systemctl status perf-guard.service --no-pager + +tail -n 100 /var/log/perf-guard.log +``` diff --git a/scripts/security/install-perf-guard.sh b/scripts/security/install-perf-guard.sh new file mode 100755 index 000000000..cd3fca4cd --- /dev/null +++ b/scripts/security/install-perf-guard.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [ "${EUID:-$(id -u)}" -ne 0 ]; then + echo "[perf-guard] must run as root" + exit 1 +fi + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +SOURCE_GUARD="$REPO_ROOT/scripts/security/perf-guard.sh" +SOURCE_SERVICE="$REPO_ROOT/scripts/security/systemd/perf-guard.service" +SOURCE_TIMER="$REPO_ROOT/scripts/security/systemd/perf-guard.timer" + +TARGET_GUARD="/usr/local/sbin/perf-guard.sh" +TARGET_SERVICE="/etc/systemd/system/perf-guard.service" +TARGET_TIMER="/etc/systemd/system/perf-guard.timer" + +if [ ! -f "$SOURCE_GUARD" ]; then + echo "[perf-guard] missing source file: $SOURCE_GUARD" + exit 1 +fi + +install -m 700 "$SOURCE_GUARD" "$TARGET_GUARD" +install -m 644 "$SOURCE_SERVICE" "$TARGET_SERVICE" +install -m 644 "$SOURCE_TIMER" "$TARGET_TIMER" + +systemctl daemon-reload +systemctl enable --now perf-guard.timer +systemctl start perf-guard.service + +echo "[perf-guard] installed" +systemctl status perf-guard.timer --no-pager | sed -n '1,20p' diff --git a/scripts/security/perf-guard.sh b/scripts/security/perf-guard.sh new file mode 100755 index 000000000..a008fe646 --- /dev/null +++ b/scripts/security/perf-guard.sh @@ -0,0 +1,164 @@ +#!/usr/bin/env bash +set -euo pipefail + +LOG_FILE="/var/log/perf-guard.log" +LOCK_FILE="/var/run/perf-guard.lock" +BACKUP_DIR="/root/security-cleanup-backup/perf-guard" + +mkdir -p "$(dirname "$LOG_FILE")" "$(dirname "$LOCK_FILE")" "$BACKUP_DIR" + +exec 9>"$LOCK_FILE" +if ! flock -n 9; then + exit 0 +fi + +log() { + printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >> "$LOG_FILE" +} + +backup_file() { + local path="$1" + if [ -f "$path" ]; then + local ts + ts=$(date '+%Y%m%d%H%M%S') + cp -a "$path" "$BACKUP_DIR/$(basename "$path").${ts}.bak" 2>/dev/null || true + fi +} + +sanitize_file() { + local file="$1" + local pattern="$2" + + [ -f "$file" ] || return 0 + + if grep -Eq "$pattern" "$file"; then + backup_file "$file" + sed -i -E "/$pattern/d" "$file" || true + log "sanitized $file" + fi +} + +kill_suspicious_processes() { + local changed=0 + + # Exact process names from known miner families. + local names=(kinsing kdevtmpfsi uhavenobotsxd perfcc perfctl pctl) + for p in "${names[@]}"; do + if pkill -9 -x "$p" 2>/dev/null; then + changed=1 + log "killed process name=$p" + fi + done + + # Command line paths used by persistent variants. + local patterns=( + '/tmp/.perf.c/' + '/root/.config/cron/perfcc' + '/bin/perfcc' + '/usr/bin/perfcc' + '/etc/data/kinsing' + '/tmp/kdevtmpfsi' + '/tmp/fwb.sh' + 'uhavenobotsxd' + '\.system3d' + ) + + for pat in "${patterns[@]}"; do + if pkill -9 -f "$pat" 2>/dev/null; then + changed=1 + log "killed process pattern=$pat" + fi + done + + if [ "$changed" -eq 1 ]; then + return 0 + fi + return 1 +} + +cleanup_paths() { + local changed=0 + local targets=( + '/tmp/.perf.c' + '/bin/.local' + '/bin/perfcc' + '/usr/bin/perfcc' + '/root/.config/cron/perfcc' + '/tmp/kdevtmpfsi' + '/tmp/fwb.sh' + '/etc/data/kinsing' + '/etc/sudoers.d/.systemd-resolved' + '/etc/cron.d/perfclean' + ) + + for path in "${targets[@]}"; do + if [ -e "$path" ]; then + backup_file "$path" + rm -rf "$path" || true + changed=1 + log "removed $path" + fi + done + + find /tmp -maxdepth 1 -name '*.uhavenobotsxd' -type f -delete 2>/dev/null || true + + if [ "$changed" -eq 1 ]; then + return 0 + fi + return 1 +} + +cleanup_cron() { + local changed=0 + local pattern='perfcc|perfctl|/tmp/\.perf\.c|/bin/perfcc|/usr/bin/perfcc|kinsing|kdevtmpfsi|\.system3d|uhavenobotsxd' + + if [ -f /var/spool/cron/root ] && grep -Eq "$pattern" /var/spool/cron/root; then + backup_file /var/spool/cron/root + sed -i -E "/$pattern/d" /var/spool/cron/root || true + chmod 600 /var/spool/cron/root || true + changed=1 + log 'cleaned /var/spool/cron/root' + fi + + local startup_files=(/root/.bash_profile /root/.bashrc /root/.profile /etc/profile /etc/bashrc) + local startup_pattern='perfcc|perfctl|/tmp/\.perf\.c|/bin/\.local/bin|/opt/\.X11-unix/profile\.sh|kinsing|kdevtmpfsi|\.system3d|uhavenobotsxd' + + for f in "${startup_files[@]}"; do + if [ -f "$f" ] && grep -Eq "$startup_pattern" "$f"; then + sanitize_file "$f" "$startup_pattern" + changed=1 + fi + done + + if [ "$changed" -eq 1 ]; then + return 0 + fi + return 1 +} + +lock_suspicious_user() { + if id sysupdate >/dev/null 2>&1; then + usermod -L -s /sbin/nologin sysupdate >/dev/null 2>&1 || true + log 'locked user sysupdate' + fi +} + +changed_any=0 + +if kill_suspicious_processes; then + changed_any=1 +fi + +if cleanup_paths; then + changed_any=1 +fi + +if cleanup_cron; then + changed_any=1 +fi + +lock_suspicious_user + +if [ "$changed_any" -eq 1 ]; then + log 'cleanup applied' +fi diff --git a/scripts/security/systemd/perf-guard.service b/scripts/security/systemd/perf-guard.service new file mode 100644 index 000000000..8b02f6f4f --- /dev/null +++ b/scripts/security/systemd/perf-guard.service @@ -0,0 +1,9 @@ +[Unit] +Description=Perf Malware Guard Cleanup +After=network.target + +[Service] +Type=oneshot +ExecStart=/usr/local/sbin/perf-guard.sh +User=root +Group=root diff --git a/scripts/security/systemd/perf-guard.timer b/scripts/security/systemd/perf-guard.timer new file mode 100644 index 000000000..e4073b01b --- /dev/null +++ b/scripts/security/systemd/perf-guard.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Run Perf Malware Guard every 15 seconds + +[Timer] +OnBootSec=20s +OnUnitActiveSec=15s +AccuracySec=1s +Unit=perf-guard.service + +[Install] +WantedBy=timers.target diff --git a/setup-server.sh b/setup-server.sh index 93bf3e078..bfdc3ae72 100755 --- a/setup-server.sh +++ b/setup-server.sh @@ -92,6 +92,12 @@ ufw allow 80/tcp ufw allow 443/tcp ufw allow 5204/tcp +# 安装恶意进程守护(如果脚本存在) +if [ -f "$(dirname "$0")/scripts/security/install-perf-guard.sh" ]; then + echo "安装 perf-guard..." + bash "$(dirname "$0")/scripts/security/install-perf-guard.sh" || echo "perf-guard 安装失败,继续执行" +fi + echo "服务器环境设置完成!" echo "" echo "下一步:" @@ -100,4 +106,3 @@ echo "2. 上传项目代码到 /var/www/ai-chatbot" echo "3. 配置环境变量 (.env.local)" echo "4. 运行 pnpm install && pnpm db:migrate && pnpm build" echo "5. 使用 PM2 启动应用" -