风过空庭,字句正徐来。
关于关于本站关于我给我点钱
更多时间线友链文件服务wiki
联系写留言发邮件GitHub
© 2024-2026 yono. | RSS 订阅 | 站点地图 | | Stay hungry. Stay foolish.
Powered by Mix Space&
白い
.
| 粤 ICP 备2024284785号-1 |
正在被0人看爆
纸白微明,未成篇章。

运维小白干掉挖矿程序

(已编辑)
24
AI·GEN

关键洞察

这篇文章上次修改于,可能部分内容已经不适用,如有疑问可询问作者。

运维小白干掉挖矿程序

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • 背景故事

    虽然我有数个网站自用在跑,但是服务器这块与我工作无关,永远是小白。

    近几个月,一直会遭遇挖矿程序入侵,但是那时候还有腾讯云的主机防护体验卡,只是会通知我然后手动点下修复就好。

    过年回来发现,体验卡到期,天塌了。老破小服务器已经满载挖矿好几天。

    年后正式启用私有部署的 git 托管管理项目代码,这个中毒问题得好好找下。其实是不想给🐕企鹅送钱。

    总而言之,目前的状况是博客前端的端口直接暴露在公网上,next.js 有某种特点(没有深究)被入侵利用,然后污染了前端容器。暂时重新拉取镜像重部署,docker-compose.yml的image段同级增加read_only: true,避免入侵下载挖矿程序,以此临时解决。

    本文主要记录一下指令长啥样,因为我记不住。

    排查流程

    立即止血

    找出最吃 CPU 的进程

    top -o %CPU
    

    切到 root

    whoami
    id
    sudo -n true; echo $?
    

    杀他妈的 例如我这个挖矿进程的 PID 是 53075,就使用 sudo kill -STOP 53075

    CodeBlock Loading...

    再看看进程

    CodeBlock Loading...

    谁拉的屎

    找到真实的可执行文件,将获得一个路径,如果需要清理可以后续进行

    CodeBlock Loading...

    查看启动命令行,其实是辅助排查,结果“空”表明不是用户手动命令行启动的

    CodeBlock Loading...

    查看进程启动时的环境变量,如果看到比较熟悉的词,在这里已经可以找到是什么应用被入侵了

    CodeBlock Loading...

    Note

    如果以上不足以找到根源应用,那么深入排查,以下指令结果无法明示,可以发给 GPT 让他辅助解析并进一步指导

    查看进程控制组,比如我这里回复0::/system.slice/docker-9cffb5dca4c53cf437c1499d7df3725132406b42b3e4873837ec1487a7aa2b46.scope,那么已经明确是CONTAINER ID 为这串数字的容器被入侵了

    CodeBlock Loading...

    查看进程基本信息

    CodeBlock Loading...

    查看父进程信息

    CodeBlock Loading...

    查看进程的网络连接情况

    CodeBlock Loading...

    详细列出进程打开的文件和网络连接

    CodeBlock Loading...

    [!NOTE]

    以上这些查询输出,如果看不懂排查不了,就直接丢给 GPT 让他指示下一步就好

    我的处理

    经过排查,在我的问题环境下,明确了是某个 docker 容器 9cffb5dca4c53cf437c1499d7df3725132406b42b3e4873837ec1487a7aa2b46 引起的,那我这里就直接查下这是个啥就行了。

    CodeBlock Loading...

    回复表明

    CodeBlock Loading...

    同时此前查找父进程表明

    CodeBlock Loading...

    另一个侧面验证是,前端镜像备份现在膨胀到了2GB,与我保存的稳定版备份400MB相去甚远。

    那我这里可以确认是博客前端的 next.js 直接暴露的问题,但是我又不会修,也不想更新前端到最新版本(in神重构了,同步更新后端和迁移好麻烦)。

    那就使用 read_only 部署就可以了,docker-compose.yml的image段同级增加read_only: true,下面是当前的。

    CodeBlock Loading...

    本地 docker 镜像压缩包的食用

    注意到,上面我使用image: shiroi:local是一个本地镜像,而不用拉取,因为这个镜像来自于一个我保存下来的稳定版压缩包。

    其实这个操作我做了好多次,但是每次都会忘得查指令,cd 到压缩包所在处->docker 加载镜像压缩包->打个人看得懂的标签。

    类似以下。

    CodeBlock Loading...

    使用不拉取的 compose 指令部署

    CodeBlock Loading...
    sudo kill -STOP <PID>
    
    top -b -n 1 | head -n 15
    
    sudo readlink -f /proc/<PID>/exe
    
    sudo sh -c 'tr “\0“ ” ” < /proc/<PID>/cmdline; echo’
    
    sudo cat /proc/<PID>/environ | tr “\0“ “\n“ | head -n 60
    
    sudo cat /proc/<PID>/cgroup
    
    sudo ps -o pid,ppid,user,cmd -p <PID>
    
    sudo ps -o pid,ppid,user,cmd -p $(ps -o ppid= -p <PID>)
    
    sudo ss -antup | grep -E "pid=<PID>," || true
    
    sudo lsof -nP -p <PID> -i 2>/dev/null | head -n 50
    
    sudo docker inspect 9cffb5dca4c53cf437c1499d7df3725132406b42b3e4873837ec1487a7aa2b46 --format 'ID={{.Id}}
    Name={{.Name}}
    Image={{.Config.Image}}
    Created={{.Created}}
    Entrypoint={{json .Config.Entrypoint}}
    Cmd={{json .Config.Cmd}}
    WorkingDir={{.Config.WorkingDir}}
    EnvCount={{len .Config.Env}}
    Mounts={{json .Mounts}}
    Ports={{json .NetworkSettings.Ports}}'
    
    ID=9cffb5dca4c53cf437c1499d7df3725132406b42b3e4873837ec1487a7aa2b46
    Name=/shiroi
    Image=ghcr.io/stbanana/shiroi:latest
    Created=2026-01-26T07:33:07.293181432Z
    ......
    
    [lighthouse@VM-20-5-opencloudos ~]$ sudo ps -o pid,ppid,user,cmd -p $(ps -o ppid= -p 53075)
        PID    PPID USER     CMD
       2206    1954 root     next-server (v
    
    YML
    version: '3'
    
    services:
      shiro:
        container_name: shiroi
        image: shiroi:local
        volumes:
          - ./.env:/app/.env
        read_only: true
        restart: always
        ports:
          - 2323:2323
    
    [root@VM-20-5-opencloudos ~]# cd /root/mx-space/Shiroi
    [root@VM-20-5-opencloudos Shiroi]# sudo docker load -i shiroi.tar
    b0f89ac7b966: Loading layer  148.4MB/148.4MB
    d3b1ea8ff6e6: Loading layer   5.39MB/5.39MB
    2497eefc5264: Loading layer  3.584kB/3.584kB
    769a089b3661: Loading layer  30.95MB/30.95MB
    8a9366fbc004: Loading layer  1.536kB/1.536kB
    556c774c2fcc: Loading layer  8.075MB/8.075MB
    55405dd49280: Loading layer  4.096kB/4.096kB
    66b48a972c24: Loading layer  24.75MB/24.75MB
    7f1566c30993: Loading layer  24.29MB/24.29MB
    911870b37b57: Loading layer  27.33MB/27.33MB
    14c1060772f2: Loading layer  6.655MB/6.655MB
    7be455708435: Loading layer  12.18MB/12.18MB
    6fdc0a038ef1: Loading layer  5.213MB/5.213MB
    ba8c6d828d78: Loading layer   2.56kB/2.56kB
    5c557125ffd5: Loading layer  160.3kB/160.3kB
    77abd848d7fc: Loading layer  110.1kB/110.1kB
    e7f72ced6a18: Loading layer  111.2MB/111.2MB
    0d71f84d6130: Loading layer  23.76MB/23.76MB
    dade50077aed: Loading layer  22.65MB/22.65MB
    Loaded image ID: sha256:8c476da1052b3d1e26bdaae875b0ac026b6c26869224732f2deee58a8349911a
    [root@VM-20-5-opencloudos Shiroi]# sudo docker tag sha256:8c476da1052b3d1e26bdaae875b0ac026b6c26869224732f2deee58a8349911a shiroi:local
    [root@VM-20-5-opencloudos Shiroi]#
    
    docker compose up -d