logo NodeSeekbeta

【复盘+自查脚本】哪吒面板漏洞被批量植入后门全过程:从发现到清理,附只读检测脚本

  • 意思是主控要先出事才中招吗

  • 完犊子。全部中招

  • @treasureu #0 我让ai优化了一下脚本,已经解决#!/usr/bin/env bash

    ============================================================

    哪吒面板入侵 IOC 自查脚本 v2

    ------------------------------------------------------------

    用途:

    排查哪吒 Dashboard / Agent 被利用后常见植入物:

    - memfd 内存马

    - 伪装 kworker / 内核线程进程

    - 执行已删除文件的进程

    - 恶意 nezha-agent / 随机 config

    - XMRig / c3pool 挖矿

    - systemlog / SystemLoger 守护复活服务

    - SSH authorized_keys 后门

    - cron / systemd timer / service 持久化

    - ld.so.preload 劫持

    - 可疑网络连接

    - 近期高风险路径文件变动

    特点:

    只读检测;不会删除、停止、修改任何东西。

    用法:

    bash nezha_ioc_check_v2.sh

    批量:

    ssh root@节点 'bash -s' < nezha_ioc_check_v2.sh

    可选环境变量:

    TRUSTED_NEZHA_ADDR_REGEX='你的面板域名|你的面板IP'

    EXCLUDE_COMM_REGEX='^(kdump|komari|kubelet)$'

    ALLOW_DELETED_EXE_REGEX='^(/usr/|/bin/|/sbin/|/lib/|/lib64/|/snap/|/app/)'

    SINCE_DAYS=14

    退出码:

    0 = 未发现已知高危 IOC

    1 = 有 WARN 项,需要人工复核

    2 = 有 ALERT 项,应按已沦陷处理

    ============================================================

    set -u
    export LC_ALL=C

    ALERT_COUNT=0
    WARN_COUNT=0
    INFO_COUNT=0

    HOSTNAME_NOW="$(hostname 2>/dev/null || echo unknown)"
    DATE_NOW="$(date '+%F %T %z' 2>/dev/null || date)"
    IS_ROOT=0
    [ "$(id -u 2>/dev/null)" = "0" ] && IS_ROOT=1

    TRUSTED_NEZHA_ADDR_REGEX="${TRUSTED_NEZHA_ADDR_REGEX:-}"
    EXCLUDE_COMM_REGEX="${EXCLUDE_COMM_REGEX:-^(kdump|komari|kubelet)$}"
    ALLOW_DELETED_EXE_REGEX="${ALLOW_DELETED_EXE_REGEX:-^(/usr/|/bin/|/sbin/|/lib/|/lib64/|/snap/|/var/lib/docker/|/var/lib/containerd/|/app/)}"
    SINCE_DAYS="${SINCE_DAYS:-14}"

    print_line() {
    printf '%s\n' "------------------------------------------------------------"
    }

    section() {
    printf '\n[%s] %s\n' "$1" "$2"
    print_line
    }

    info() {
    INFO_COUNT=$((INFO_COUNT + 1))
    printf ' [信息] %s\n' "$*"
    }

    warn() {
    WARN_COUNT=$((WARN_COUNT + 1))
    printf ' [警] %s\n' "$*"
    }

    alert() {
    ALERT_COUNT=$((ALERT_COUNT + 1))
    printf ' [高危] %s\n' "$*"
    }

    ok() {
    printf ' [未发现] %s\n' "$*"
    }

    have_cmd() {
    command -v "$1" >/dev/null 2>&1
    }

    safe_cat() {
    cat "$1" 2>/dev/null
    }

    safe_readlink() {
    readlink "$1" 2>/dev/null
    }

    proc_pids() {
    find /proc -maxdepth 1 -type d -regex '/proc/[0-9]+' 2>/dev/null | sed 's#/proc/##' | sort -n
    }

    get_cmdline() {
    tr '\0' ' ' < "/proc/$1/cmdline" 2>/dev/null | sed 's/[[:space:]]*$//'
    }

    get_comm() {
    safe_cat "/proc/$1/comm" | head -n 1
    }

    get_ppid() {
    awk '{print $4}' "/proc/$1/stat" 2>/dev/null
    }

    get_user_by_uid() {
    awk -F: -v uid="$1" '$3 == uid {print $1; exit}' /etc/passwd 2>/dev/null
    }

    get_uid_of_pid() {
    awk '/^Uid:/ {print $2; exit}' "/proc/$1/status" 2>/dev/null
    }

    is_kernel_thread_like_name() {
    case "$1" in
    kworker*|ksoftirqd*|kthreadd|migration*|watchdog*|rcu_|rcuos|rcuop*|cpuhp*|idle_inject*|kauditd|kswapd*|oom_reaper|writeback|kintegrityd|kblockd|ata_sff|md|edac-poller)
    return 0
    ;;
    *)
    return 1
    ;;
    esac
    }

    is_probably_real_kernel_thread() {
    pid="$1"
    exe="$(safe_readlink "/proc/$pid/exe")"
    ppid="$(get_ppid "$pid")"
    if [ -z "$exe" ] && [ "$ppid" = "2" ]; then
    return 0
    fi
    return 1
    }

    print_file_preview() {
    file="$1"
    max_lines="${2:-20}"

    if [ -f "$file" ]; then
    sed -n "1,${max_lines}p" "$file" 2>/dev/null | sed 's/^/ /'
    fi
    }

    echo "============================================================"
    echo " 哪吒入侵 IOC 自查 v2"
    echo " 主机: $HOSTNAME_NOW"
    echo " 时间: $DATE_NOW"
    echo " 用户: $(id 2>/dev/null || echo unknown)"
    echo "============================================================"

    if [ "$IS_ROOT" -ne 1 ]; then
    warn "当前不是 root,部分 /proc、其他用户 authorized_keys、systemd 信息可能读不到;建议用 root 跑一次。"
    fi

    section "1" "memfd 内存马 / 无文件执行体"

    found_memfd=0

    for pid in $(proc_pids); do
    exe="$(safe_readlink "/proc/$pid/exe")"
    cmd="$(get_cmdline "$pid")"
    comm="$(get_comm "$pid")"
    uid="$(get_uid_of_pid "$pid")"
    user="$(get_user_by_uid "$uid")"
    [ -z "$user" ] && user="$uid"

    if printf '%s' "$exe" | grep -qiE 'memfd:|/memfd:'; then
    alert "PID=$pid USER=$user COMM=$comm EXE=$exe CMD=${cmd:-<empty>}"
    found_memfd=1
    fi

    if [ -d "/proc/$pid/fd" ]; then
    memfd_fds="$(find "/proc/$pid/fd" -maxdepth 1 -type l -lname 'memfd:' 2>/dev/null | head -n 5)"
    if [ -n "$memfd_fds" ]; then
    warn "PID=$pid USER=$user COMM=$comm 存在 memfd fd,需核查 CMD=${cmd:-<empty>}"
    printf '%s\n' "$memfd_fds" | sed 's/^/ /'
    found_memfd=1
    fi
    fi
    done

    [ "$found_memfd" -eq 0 ] && ok "未发现 /proc/PID/exe 或 fd 指向 memfd 的进程"

    section "2" "伪装内核线程 / kworker 类进程"

    found_fake_kernel=0

    for pid in $(proc_pids); do
    comm="$(get_comm "$pid")"
    [ -z "$comm" ] && continue

    if is_kernel_thread_like_name "$comm"; then
    if is_probably_real_kernel_thread "$pid"; then
    continue
    fi

    exe="$(safe_readlink "/proc/$pid/exe")"
    ppid="$(get_ppid "$pid")"
    cmd="$(get_cmdline "$pid")"
    uid="$(get_uid_of_pid "$pid")"
    user="$(get_user_by_uid "$uid")"
    [ -z "$user" ] && user="$uid"
    
    if [ -n "$exe" ]; then
      if ! printf '%s' "$comm" | grep -Eq "$EXCLUDE_COMM_REGEX"; then
        alert "疑似伪装内核线程 PID=$pid PPID=$ppid USER=$user COMM=$comm EXE=$exe CMD=${cmd:-<empty>}"
        found_fake_kernel=1
      fi
    fi
    

    fi
    done

    [ "$found_fake_kernel" -eq 0 ] && ok "未发现明显伪装 kworker / 内核线程的用户态进程"

    section "3" "执行已删除文件的进程"

    found_deleted_exe=0

    for pid in $(proc_pids); do
    exe="$(safe_readlink "/proc/$pid/exe")"
    case "$exe" in
    "(deleted)")
    cmd="$(get_cmdline "$pid")"
    comm="$(get_comm "$pid")"
    uid="$(get_uid_of_pid "$pid")"
    user="$(get_user_by_uid "$uid")"
    [ -z "$user" ] && user="$uid"

      clean_exe="$(printf '%s' "$exe" | sed 's/ (deleted)$//')"
    
      if printf '%s' "$clean_exe" | grep -Eq "$ALLOW_DELETED_EXE_REGEX"; then
        warn "PID=$pid USER=$user COMM=$comm EXE=$exe 属于白名单路径,但仍建议核查是否为升级残留"
      else
        alert "PID=$pid USER=$user COMM=$comm EXE=$exe CMD=${cmd:-<empty>}"
      fi
      found_deleted_exe=1
      ;;
    

    esac
    done

    [ "$found_deleted_exe" -eq 0 ] && ok "未发现 exe 指向 deleted 文件的进程"

    section "4" "哪吒 Agent / Dashboard 残留与异常配置"

    found_nezha=0

    if pgrep -af 'nezha|dashboard|agent' >/tmp/nezha_ioc_ps.$$ 2>/dev/null; then
    info "发现包含 nezha/dashboard/agent 字样的进程:"
    sed 's/^/ /' /tmp/nezha_ioc_ps.$$
    found_nezha=1

    if grep -Ei 'config-[a-z0-9]+.ya?ml|nezha-agent-[a-z0-9]+|/opt/nezha/agent/config-' /tmp/nezha_ioc_ps.$$ >/dev/null 2>&1; then
    alert "发现疑似随机后缀 nezha-agent / config 进程"
    fi
    fi
    rm -f /tmp/nezha_ioc_ps.$$ 2>/dev/null

    if [ -d /opt/nezha ]; then
    warn "/opt/nezha 目录存在;若已确认中招,建议人工核查后停用并重装相关组件"
    found_nezha=1
    fi

    if [ -d /opt/nezha/agent ]; then
    info "/opt/nezha/agent 内容:"
    find /opt/nezha/agent -maxdepth 2 -mindepth 1 2>/dev/null | sed 's/^/ /' | head -n 80
    fi

    if find /opt/nezha/agent -maxdepth 2 -type f ( -name 'config-.yml' -o -name 'config-.yaml' ) 2>/dev/null | grep . >/tmp/nezha_ioc_configs.$$; then
    alert "发现随机后缀哪吒 agent config:"
    sed 's/^/ /' /tmp/nezha_ioc_configs.$$
    found_nezha=1
    fi
    rm -f /tmp/nezha_ioc_configs.$$ 2>/dev/null

    if find /etc/systemd/system /lib/systemd/system /usr/lib/systemd/system
    -maxdepth 1 -type f ( -name 'nezha.service' -o -name 'nezha-agent-*.service' )
    2>/dev/null | grep . >/tmp/nezha_ioc_units.$$; then

    warn "发现哪吒相关 systemd service:"
    sed 's/^/ /' /tmp/nezha_ioc_units.$$
    found_nezha=1

    while IFS= read -r unit; do
    [ -f "$unit" ] || continue
    if grep -Eiq 'config-[a-z0-9]+.ya?ml|nezha-agent-[a-z0-9]+' "$unit"; then
    alert "service 内含随机后缀配置或 agent 名称:$unit"
    print_file_preview "$unit" 30
    fi
    done < /tmp/nezha_ioc_units.$$
    fi
    rm -f /tmp/nezha_ioc_units.$$ 2>/dev/null

    if find /opt/nezha /etc/systemd/system /lib/systemd/system /usr/lib/systemd/system
    -type f 2>/dev/null | xargs grep -IEl 'nz_client_secret|nezha|dashboard|grpc|tls' 2>/dev/null | grep . >/tmp/nezha_ioc_grep.$$; then
    info "发现哪吒相关配置文件线索:"
    sed 's/^/ /' /tmp/nezha_ioc_grep.$$ | head -n 80
    fi
    rm -f /tmp/nezha_ioc_grep.$$ 2>/dev/null

    if [ -n "$TRUSTED_NEZHA_ADDR_REGEX" ]; then
    if find /opt/nezha /etc/systemd/system /lib/systemd/system /usr/lib/systemd/system
    -type f 2>/dev/null | xargs grep -IEl 'nezha|dashboard|grpc|client_secret|server' 2>/dev/null | while IFS= read -r f; do
    if ! grep -Eq "$TRUSTED_NEZHA_ADDR_REGEX" "$f" 2>/dev/null; then
    echo "$f"
    fi
    done | grep . >/tmp/nezha_ioc_untrusted.$$; then
    warn "以下哪吒相关文件未匹配 TRUSTED_NEZHA_ADDR_REGEX,需核查是否连到第三方主控:"
    sed 's/^/ /' /tmp/nezha_ioc_untrusted.$$ | head -n 80
    fi
    rm -f /tmp/nezha_ioc_untrusted.$$ 2>/dev/null
    else
    info "未设置 TRUSTED_NEZHA_ADDR_REGEX,跳过哪吒主控地址白名单校验"
    fi

    [ "$found_nezha" -eq 0 ] && ok "未发现明显哪吒残留"

    section "5" "XMRig / c3pool 挖矿"

    found_miner=0

    if [ -e /root/c3pool ]; then
    alert "/root/c3pool 存在"
    found_miner=1
    fi

    if pgrep -af 'xmrig|c3pool|monero|xmr|stratum|pool.supportxmr|nanopool|minexmr' >/tmp/nezha_ioc_miner_ps.$$ 2>/dev/null; then
    alert "发现疑似挖矿相关进程:"
    sed 's/^/ /' /tmp/nezha_ioc_miner_ps.$$
    found_miner=1
    fi
    rm -f /tmp/nezha_ioc_miner_ps.$$ 2>/dev/null

    for f in
    /etc/systemd/system/c3pool_miner.service
    /lib/systemd/system/c3pool_miner.service
    /usr/lib/systemd/system/c3pool_miner.service
    do
    if [ -e "$f" ]; then
    alert "发现 c3pool_miner service:$f"
    print_file_preview "$f" 30
    found_miner=1
    fi
    done

    if find /etc/systemd/system /lib/systemd/system /usr/lib/systemd/system
    -maxdepth 1 -type f 2>/dev/null | xargs grep -IEl 'xmrig|c3pool|stratum|monero|supportxmr|minexmr' 2>/dev/null | grep . >/tmp/nezha_ioc_miner_units.$$; then
    alert "systemd unit 中发现挖矿关键词:"
    sed 's/^/ /' /tmp/nezha_ioc_miner_units.$$
    found_miner=1
    fi
    rm -f /tmp/nezha_ioc_miner_units.$$ 2>/dev/null

    [ "$found_miner" -eq 0 ] && ok "未发现常见 XMRig / c3pool 挖矿痕迹"

    section "6" "systemlog / SystemLoger 守护复活服务"

    found_systemlog=0

    if pgrep -af 'SystemLoger|systemlog' >/tmp/nezha_ioc_systemlog_ps.$$ 2>/dev/null; then
    alert "发现疑似 systemlog / SystemLoger 进程:"
    sed 's/^/ /' /tmp/nezha_ioc_systemlog_ps.$$
    found_systemlog=1
    fi
    rm -f /tmp/nezha_ioc_systemlog_ps.$$ 2>/dev/null

    for p in
    /opt/systemlog
    /etc/systemd/system/systemlog.service
    /lib/systemd/system/systemlog.service
    /usr/lib/systemd/system/systemlog.service
    do
    if [ -e "$p" ]; then
    alert "发现守护/复活服务痕迹:$p"
    [ -f "$p" ] && print_file_preview "$p" 40
    found_systemlog=1
    fi
    done

    if find /etc/systemd/system /lib/systemd/system /usr/lib/systemd/system
    -maxdepth 1 -type f 2>/dev/null | xargs grep -IEl 'SystemLoger|/opt/systemlog|systemlog' 2>/dev/null | grep . >/tmp/nezha_ioc_systemlog_units.$$; then
    alert "systemd unit 中发现 systemlog/SystemLoger 关键词:"
    sed 's/^/ /' /tmp/nezha_ioc_systemlog_units.$$
    found_systemlog=1
    fi
    rm -f /tmp/nezha_ioc_systemlog_units.$$ 2>/dev/null

    [ "$found_systemlog" -eq 0 ] && ok "未发现 systemlog / SystemLoger 守护痕迹"

    section "7" "SSH authorized_keys 后门"

    found_sshkey=0

    check_auth_keys_file() {
    ak="$1"
    owner_hint="$2"

    [ -f "$ak" ] || return 0

    count="$(grep -Ec '^(ssh-rsa|ssh-ed25519|ecdsa-sha2-|sk-ssh-|sk-ecdsa-)' "$ak" 2>/dev/null || true)"
    info "$owner_hint authorized_keys 公钥数: $count ($ak)"

    if grep -Eiq 'gary|c3pool|nezha|xmrig|systemlog|SystemLoger|backdoor|root@.*ubuntu|root@.*debian' "$ak" 2>/dev/null; then
    alert "$owner_hint authorized_keys 含可疑注释或关键词:$ak"
    grep -Ein 'gary|c3pool|nezha|xmrig|systemlog|SystemLoger|backdoor|root@.*ubuntu|root@.*debian' "$ak" 2>/dev/null | sed 's/^/ /'
    found_sshkey=1
    fi

    if awk 'length($0) > 900 {print NR ":" substr($0,1,160) "..."}' "$ak" 2>/dev/null | grep . >/tmp/nezha_ioc_longkey.$$; then
    warn "$owner_hint authorized_keys 存在超长行,需确认是否为合法证书型 key:$ak"
    sed 's/^/ /' /tmp/nezha_ioc_longkey.$$
    found_sshkey=1
    fi
    rm -f /tmp/nezha_ioc_longkey.$$ 2>/dev/null

    if grep -Ev '^\s*$|^\s*#|^(command=|from=|environment=|no-|permit|restrict|ssh-rsa|ssh-ed25519|ecdsa-sha2-|sk-ssh-|sk-ecdsa-)' "$ak" 2>/dev/null | grep . >/tmp/nezha_ioc_badkeyline.$$; then
    warn "$owner_hint authorized_keys 有格式异常行:$ak"
    sed 's/^/ /' /tmp/nezha_ioc_badkeyline.$$
    found_sshkey=1
    fi
    rm -f /tmp/nezha_ioc_badkeyline.$$ 2>/dev/null
    }

    check_auth_keys_file "/root/.ssh/authorized_keys" "root"

    while IFS=: read -r user _ uid _ _ home shell; do
    [ -n "$user" ] || continue
    [ -n "$home" ] || continue

    case "$shell" in
    /nologin|/false) ;;
    *)
    if [ "$home" != "/root" ]; then
    check_auth_keys_file "$home/.ssh/authorized_keys" "$user"
    fi
    ;;
    esac
    done < /etc/passwd

    if [ "$found_sshkey" -eq 0 ]; then
    ok "未发现带常见可疑关键词的 authorized_keys;仍建议逐把人工确认"
    fi

    section "8" "cron / anacron 持久化"

    found_cron=0

    for u in $(cut -d: -f1 /etc/passwd 2>/dev/null); do
    cron_content="$(crontab -l -u "$u" 2>/dev/null | grep -Ev '^\s*#|^\s*$' || true)"
    if [ -n "$cron_content" ]; then
    warn "用户 $u 存在 cron,需核查:"
    printf '%s\n' "$cron_content" | sed 's/^/ /'
    found_cron=1

    if printf '%s\n' "$cron_content" | grep -Eiq 'curl|wget|base64|/tmp/|/dev/shm|nc |ncat|bash -c|sh -c|python|perl|php|chmod \+x|xmrig|c3pool|systemlog|nezha'; then
      alert "用户 $u 的 cron 含高风险命令关键词"
    fi
    

    fi
    done

    if find /etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.weekly /etc/cron.monthly /var/spool/cron /var/spool/cron/crontabs
    -type f 2>/dev/null | xargs grep -IEn 'curl|wget|base64|/tmp/|/dev/shm|nc |ncat|bash -c|sh -c|python|perl|php|chmod +x|xmrig|c3pool|systemlog|nezha' 2>/dev/null | grep . >/tmp/nezha_ioc_cronfiles.$$; then
    alert "系统 cron 文件含高风险关键词:"
    sed 's/^/ /' /tmp/nezha_ioc_cronfiles.$$ | head -n 120
    found_cron=1
    fi
    rm -f /tmp/nezha_ioc_cronfiles.$$ 2>/dev/null

    [ "$found_cron" -eq 0 ] && ok "未发现明显 cron 持久化"

    section "9" "systemd service / timer 持久化"

    found_systemd=0

    if have_cmd systemctl; then
    if systemctl list-timers --all --no-pager 2>/dev/null | grep -Ei 'systemlog|nezha|xmrig|c3pool|tmp|shm|curl|wget' >/tmp/nezha_ioc_timers.$$; then
    warn "发现可疑 systemd timer:"
    sed 's/^/ /' /tmp/nezha_ioc_timers.$$
    found_systemd=1
    fi
    rm -f /tmp/nezha_ioc_timers.$$ 2>/dev/null

    if systemctl list-units --type=service --all --no-pager 2>/dev/null | grep -Ei 'systemlog|SystemLoger|nezha-agent-[a-z0-9]+|c3pool|xmrig' >/tmp/nezha_ioc_services.$$; then
    alert "发现可疑 systemd service:"
    sed 's/^/ /' /tmp/nezha_ioc_services.$$
    found_systemd=1
    fi
    rm -f /tmp/nezha_ioc_services.$$ 2>/dev/null
    else
    info "未找到 systemctl,跳过 systemd 运行状态检查"
    fi

    if find /etc/systemd/system /lib/systemd/system /usr/lib/systemd/system
    -maxdepth 1 -type f 2>/dev/null | xargs grep -IEn 'curl|wget|base64|/tmp/|/dev/shm|bash -c|sh -c|xmrig|c3pool|systemlog|SystemLoger|nezha-agent-[a-z0-9]+|config-[a-z0-9]+.ya?ml' 2>/dev/null | grep . >/tmp/nezha_ioc_systemd_files.$$; then
    alert "systemd unit 文件含高风险关键词:"
    sed 's/^/ /' /tmp/nezha_ioc_systemd_files.$$ | head -n 160
    found_systemd=1
    fi
    rm -f /tmp/nezha_ioc_systemd_files.$$ 2>/dev/null

    [ "$found_systemd" -eq 0 ] && ok "未发现明显 systemd 持久化"

    section "10" "ld.so.preload 劫持"

    if [ -f /etc/ld.so.preload ]; then
    alert "/etc/ld.so.preload 存在,默认通常不应存在,需确认是否被劫持:"
    print_file_preview /etc/ld.so.preload 50

    while IFS= read -r sofile; do
    [ -z "$sofile" ] && continue
    case "$sofile" in
    #*) continue ;;
    esac

    if [ -e "$sofile" ]; then
      info "preload 目标存在:$sofile"
      ls -la "$sofile" 2>/dev/null | sed 's/^/      /'
    else
      warn "preload 目标不存在:$sofile"
    fi
    

    done < /etc/ld.so.preload
    else
    ok "未发现 /etc/ld.so.preload"
    fi

    section "11" "可疑网络连接"

    found_net=0

    if have_cmd ss; then
    ss -tunap 2>/dev/null | grep -Ei 'xmrig|c3pool|nezha|systemlog|SystemLoger|:3333|:4444|:5555|:7777|:14444|:18080|:19999' >/tmp/nezha_ioc_net.$$
    elif have_cmd netstat; then
    netstat -tunap 2>/dev/null | grep -Ei 'xmrig|c3pool|nezha|systemlog|SystemLoger|:3333|:4444|:5555|:7777|:14444|:18080|:19999' >/tmp/nezha_ioc_net.$$
    else
    : > /tmp/nezha_ioc_net.$$
    info "未找到 ss/netstat,跳过网络连接检查"
    fi

    if [ -s /tmp/nezha_ioc_net.$$ ]; then
    warn "发现可能相关的网络连接或监听:"
    sed 's/^/ /' /tmp/nezha_ioc_net.$$ | head -n 120
    found_net=1
    fi
    rm -f /tmp/nezha_ioc_net.$$ 2>/dev/null

    if have_cmd ss; then
    if ss -tunap 2>/dev/null | awk '
    /ESTAB/ && $5 !~ /^(127.0.0.1|::1)/ {
    print
    }' | grep -Ei ':(3333|4444|5555|7777|14444|18080|19999)\b' >/tmp/nezha_ioc_poolports.$$; then
    alert "发现常见矿池端口连接:"
    sed 's/^/ /' /tmp/nezha_ioc_poolports.$$
    found_net=1
    fi
    rm -f /tmp/nezha_ioc_poolports.$$ 2>/dev/null
    fi

    [ "$found_net" -eq 0 ] && ok "未发现明显挖矿/后门相关网络连接关键词"

    section "12" "高风险目录近期变动"

    found_recent=0

    if ! printf '%s' "$SINCE_DAYS" | grep -Eq '^[0-9]+$'; then
    SINCE_DAYS=14
    fi

    for dir in
    /tmp
    /var/tmp
    /dev/shm
    /opt
    /root
    /etc/systemd/system
    /var/spool/cron
    /var/spool/cron/crontabs
    do
    [ -d "$dir" ] || continue

    if find "$dir" -xdev -type f -mtime "-$SINCE_DAYS"
    ( -perm -111 -o -name '.service' -o -name '.timer' -o -name '.sh' -o -name '.yml' -o -name '*.yaml' )
    2>/dev/null | head -n 80 | grep . >/tmp/nezha_ioc_recent.$$; then
    warn "$dir 最近 $SINCE_DAYS 天存在可执行/配置/service/timer 文件变动:"
    while IFS= read -r f; do
    ls -la "$f" 2>/dev/null | sed 's/^/ /'
    done < /tmp/nezha_ioc_recent.$$
    found_recent=1
    fi
    rm -f /tmp/nezha_ioc_recent.$$ 2>/dev/null
    done

    [ "$found_recent" -eq 0 ] && ok "未发现高风险目录近期明显可疑变动"

    section "13" "账户与 sudo 权限粗查"

    found_account=0

    if awk -F: '($3 == 0) {print $1 ":" $3 ":" $6 ":" $7}' /etc/passwd 2>/dev/null | grep -v '^root:' >/tmp/nezha_ioc_uid0.$$; then
    if [ -s /tmp/nezha_ioc_uid0.$$ ]; then
    alert "发现非 root 的 UID 0 账号:"
    sed 's/^/ /' /tmp/nezha_ioc_uid0.$$
    found_account=1
    fi
    fi
    rm -f /tmp/nezha_ioc_uid0.$$ 2>/dev/null

    if grep -RInE 'NOPASSWD|ALL=(ALL(:ALL)?) ALL|/bin/bash|/bin/sh' /etc/sudoers /etc/sudoers.d 2>/dev/null | grep -vE '^\s*#' >/tmp/nezha_ioc_sudo.$$; then
    warn "sudoers 中存在高权限规则,需核查是否为预期:"
    sed 's/^/ /' /tmp/nezha_ioc_sudo.$$ | head -n 120
    found_account=1
    fi
    rm -f /tmp/nezha_ioc_sudo.$$ 2>/dev/null

    [ "$found_account" -eq 0 ] && ok "未发现明显异常 UID 0 账号;sudo 规则未命中高风险关键词"

    section "14" "登录与认证日志线索"

    if have_cmd last; then
    info "最近登录记录 last -n 20:"
    last -n 20 2>/dev/null | sed 's/^/ /'
    else
    info "未找到 last 命令"
    fi

    auth_log_found=0
    for logf in /var/log/auth.log /var/log/secure; do
    [ -f "$logf" ] || continue
    auth_log_found=1

    info "$logf 最近 SSH 登录/失败摘要:"
    grep -Ei 'Accepted|Failed|Invalid user|authentication failure|sudo|session opened' "$logf" 2>/dev/null | tail -n 60 | sed 's/^/ /'
    done

    [ "$auth_log_found" -eq 0 ] && info "未找到 /var/log/auth.log 或 /var/log/secure"

    section "15" "复活检查建议"

    cat <<'EOF'
    [说明] 如果前面命中了 memfd、kworker 伪装、deleted exe、systemlog、c3pool:
    1. 先记录 PID、exe、cmdline、ppid、网络连接。
    2. 人工 kill 可疑 PID 后,等待 30-60 秒再重新跑本脚本。
    3. 如果 PID 变了又出现,说明仍有守护/复活点。
    4. 被 root 控制过的机器,清理只能止血,最终建议滚动重装。
    EOF

    echo
    echo "============================================================"
    echo " 自查结果汇总"
    echo "------------------------------------------------------------"
    echo " 高危 ALERT : $ALERT_COUNT"
    echo " 警告 WARN : $WARN_COUNT"
    echo " 信息 INFO : $INFO_COUNT"
    echo "============================================================"

    if [ "$ALERT_COUNT" -gt 0 ]; then
    echo " 结论: 命中高危 IOC。建议按已沦陷处理,隔离、取证、轮换凭据、滚动重装。"
    exit 2
    elif [ "$WARN_COUNT" -gt 0 ]; then
    echo " 结论: 存在需要人工复核的可疑项。未直接确认沦陷,但不建议忽略。"
    exit 1
    else
    echo " 结论: 未发现本脚本覆盖范围内的已知 IOC。注意这不等于绝对安全。"
    exit 0
    fi

    注意:
    

    脚本只读自查,不负责清理
    命中 [高危] 不等于自动删除,先取证再处理。
    跑完没报警也不代表机器绝对干净
    root 被控过后,最终可信方案还是重装;脚本只能覆盖已知 IOC。
    先堵入口再清理
    Dashboard/Agent 不处理,清掉后门也可能被重新下发。

  • 谢谢分享

  • 如果重新安装了系统,是不是就没事了,没敢安装哪吒了,只部署了自己的工具,现在没有探针跟瞎子一样,komari 安全吗。

  • 标记一处地点

  • @tablerjoy #14 注意看你这个随机config文件就说明已经中招了

  • @sudoerx #18 考虑到大家情况都不一样就只做了排查,建议还是直接重装比较好

  • @kkbera #17 我也是,当时根本没注意这个disable

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有71941位seeker

🎉欢迎新用户🎉