feat(security): add perf-guard malware cleanup and auto-install
This commit is contained in:
parent
b34fb88c98
commit
932b1762f2
@ -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}"
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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}"
|
||||
|
||||
|
||||
29
docs/security/perf-guard.md
Normal file
29
docs/security/perf-guard.md
Normal file
@ -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
|
||||
```
|
||||
34
scripts/security/install-perf-guard.sh
Executable file
34
scripts/security/install-perf-guard.sh
Executable file
@ -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'
|
||||
164
scripts/security/perf-guard.sh
Executable file
164
scripts/security/perf-guard.sh
Executable file
@ -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
|
||||
9
scripts/security/systemd/perf-guard.service
Normal file
9
scripts/security/systemd/perf-guard.service
Normal file
@ -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
|
||||
11
scripts/security/systemd/perf-guard.timer
Normal file
11
scripts/security/systemd/perf-guard.timer
Normal file
@ -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
|
||||
@ -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 启动应用"
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user