logo NodeSeekbeta

一起通过 SSH 爆破入侵并利用 Cron 实现持久化的攻击事件分析

原文:https://www.nodeseek.com/post-361893-1
本文直接提交排查的原始日志给AI,文章由AI生成,底部可以看到详细排查信息。

1. 执行摘要 (Executive Summary)

本报告详细分析了一起针对 Debian 服务器的攻击事件。攻击者于 2025年06月07日 通过对 root 账户进行 SSH 暴力破解获得初始访问权限。成功入侵后,攻击者迅速部署了一个伪装成共享库(.so 文件)的恶意可执行程序,并通过修改系统级 crontab 文件创建了一个每分钟执行的计划任务,以此实现持久化控制。本次调查通过对系统日志、文件系统时间戳和配置文件进行关联分析,成功还原了完整的攻击链。

2. 攻击链分析 (Attack Chain Analysis)

本次攻击过程清晰,符合一个典型的攻击生命周期:初始访问 -> 执行与持久化。

阶段一:初始访问 (Initial Access)
  • 技术描述: 攻击者利用自动化工具对服务器的 SSH 端口(22)进行密码暴力破解。
  • 证据溯源:
    • sshd 服务日志显示,攻击者 IP 101.47.38.17 在成功登录前有大量失败尝试(共计 132 次失败),这是暴力破解的明确特征。
    • 2025-06-07 11:59:03,该 IP 成功使用密码登录 root 账户。
      Jun 07 11:59:03 debian sshd[746]: Accepted password for root from 101.47.38.17 port 39078 ssh2
      
    • 紧接着在 10 秒后,另一 IP 95.214.232.18 也成功登录,表明攻击者可能使用多个 IP 地址进行操作。
阶段二:执行与持久化 (Execution & Persistence)
  • 技术描述: 攻击者在获得权限后,立即执行了一系列操作以确保其恶意软件能够持续运行,核心手段是利用 Cron 计划任务。
  • 证据溯源:
    1. 植入恶意负载 (Payload Drop):

      • 攻击者将一个名为 libgdi.so.0.8.2 的 ELF 可执行文件放置在 /usr/lib/ 目录下,伪装成系统库文件。
      • 其文件修改时间(Modify)被伪造成 2022-12-19,意图躲避管理员检查。但其创建时间(Birth 2025-06-07 12:00:02.452000000 暴露了其真实植入时间。
    2. 创建启动脚本 (Launcher Creation):

      • 攻击者在根目录 /下创建了一个名为 /.mod 的 shell 脚本,其唯一作用是执行上述的恶意负载。
        # cat /.mod
        #!/bin/bash
        /usr/lib/libgdi.so.0.8.2
        
      • 该脚本的创建时间 2025-06-07 12:00:02.460000000 与主负载文件高度一致。
    3. 建立持久化机制 (Persistence Setup):

      • 攻击者修改了系统级的 /etc/crontab 文件,添加了以下恶意条目:
        */1 * * * * root /.mod
        
      • 此条目使系统每分钟以 root 权限执行 /.mod 脚本,从而启动恶意程序。
      • /etc/crontab 文件的修改时间 2025-06-07 12:00:02.464000000 与恶意文件的创建时间在同一秒内,形成了完整的证据链。
    4. 验证执行:

      • 系统日志显示,cron 服务从 2025-06-07 12:01:01 开始,每分钟都准时执行了 /.mod 命令,证实持久化机制已成功激活。
        # journalctl | grep '/\.mod'
        Jun 07 12:01:01 debian CRON[844]: (root) CMD (/.mod )
        Jun 07 12:02:01 debian CRON[860]: (root) CMD (/.mod )
        
3. 失陷指标 (Indicators of Compromise - IoCs)

以下是本次事件中确认的失陷指标,可用于在其他系统中进行排查。

  • 文件哈希 (MD5):

    • 53e3923bd546ac297e3d1c7d97cd36a9
  • 恶意文件路径:

    • /.mod
    • /usr/lib/libgdi.so.0.8.2
  • 攻击源 IP 地址:

    • 101.47.38.17
    • 95.214.232.18
  • 持久化特征:

    • /etc/crontab 文件中包含 /.mod 相关的恶意条目。
4. 清理与加固建议 (Remediation & Hardening)
紧急清理步骤
  1. 隔离主机: 断开服务器的公网连接,防止进一步的数据泄露或横向移动。
  2. 清除持久化: 编辑 /etc/crontab 文件,删除 */1 * * * * root /.mod 这一行。
  3. 终止恶意进程: 找到由 /.modlibgdi.so.0.8.2 启动的进程并将其终止(kill -9 <PID>)。
  4. 删除恶意文件: 执行 rm /.modrm /usr/lib/libgdi.so.0.8.2
  5. 强制更新凭证: 立即重置 root 用户及系统上所有其他用户的密码,确保使用高强度复杂密码。
长期安全加固建议
  1. SSH 安全强化:
    • 禁止 root 用户直接通过密码登录(修改 /etc/ssh/sshd_config,设置 PermitRootLogin prohibit-passwordPermitRootLogin no)。
    • 强制使用密钥对(Key-Pair)进行认证。
    • 修改 SSH 默认端口(22)。
  2. 访问控制:
    • 配置防火墙(如 ufwiptables),只开放必要的服务端口。
    • 部署如 fail2bansshguard 等工具,自动阻止尝试暴力破解的 IP。
  3. 系统完整性监控:
    • 部署文件完整性监控工具(如 AIDETripwire),定期检查关键系统文件的变更。
  4. 纵深防御:
    • 强烈建议: 鉴于 root 权限已失陷,无法 100% 确定攻击者是否留有更深层次的后门(如 Kernel Rootkit)。最安全的选择是备份重要数据后,重装操作系统

原始排查信息:

root@debian:~# cat /etc/crontab 
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.daily; }
47 6    * * 7   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.weekly; }
52 6    1 * *   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.monthly; }
#

*/1 * * * * root /.mod 
root@debian:~# stat /etc/crontab
  File: /etc/crontab
  Size: 1067            Blocks: 8          IO Block: 4096   regular file
Device: 8,2     Inode: 2752682     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2025-06-11 21:19:28.696000000 -0400
Modify: 2025-06-07 12:00:02.464000000 -0400
Change: 2025-06-07 12:00:02.464000000 -0400
 Birth: 2025-06-07 11:20:30.304000000 -0400
root@debian:~# file /.mod 
/.mod: Bourne-Again shell script, ASCII text executable
root@debian:~# stat /.mod
  File: /.mod
  Size: 36              Blocks: 8          IO Block: 4096   regular file
Device: 8,2     Inode: 20          Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2025-06-11 12:01:01.200000000 -0400
Modify: 2025-06-07 12:00:02.460000000 -0400
Change: 2025-06-07 12:00:02.460000000 -0400
 Birth: 2025-06-07 12:00:02.460000000 -0400

cat /.mod 
#!/bin/bash
/usr/lib/libgdi.so.0.8.2

root@debian:~# file /usr/lib/libgdi.so.0.8.2
/usr/lib/libgdi.so.0.8.2: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=9aweAb3NxvdjkKSF5j5z/-6qEjXc-SfQjEyoBRUWa/M_49j5sTTJLMK3MMdr3g/OVx2LvkSFU1AaVRWkhzu, stripped
root@debian:~# stat /usr/lib/libgdi.so.0.8.2
  File: /usr/lib/libgdi.so.0.8.2
  Size: 5242880         Blocks: 10240      IO Block: 4096   regular file
Device: 8,2     Inode: 1188739     Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2025-06-11 21:20:01.740000000 -0400
Modify: 2022-12-19 01:06:38.000000000 -0500
Change: 2025-06-11 21:19:29.004000000 -0400
 Birth: 2025-06-07 12:00:02.452000000 -0400
root@debian:~# md5sum /usr/lib/libgdi.so.0.8.2
53e3923bd546ac297e3d1c7d97cd36a9  /usr/lib/libgdi.so.0.8.2


journalctl | grep '/\.mod' | more 
Jun 07 12:01:01 debian CRON[844]: (root) CMD (/.mod )
Jun 07 12:02:01 debian CRON[860]: (root) CMD (/.mod )


journalctl _COMM=sshd --since "2025-06-07 11:50:00" --until "2025-06-07 12:10:00" | grep 'Accepted'
Jun 07 11:59:03 debian sshd[746]: Accepted password for root from 101.47.38.17 port 39078 ssh2
Jun 07 11:59:13 debian sshd[764]: Accepted password for root from 95.214.232.18 port 55749 ssh2

root@debian:~# journalctl _COMM=sshd | grep '101.47.38.17' | grep -E 'Failed password|Accepted password' | wc -l
133
root@debian:~# journalctl _COMM=sshd | grep '95.214.232.18' | grep -E 'Failed password|Accepted password' | wc -l
1
  • 使用 SSH Key

  • ...都是机器人。。分析有什么用。。

  • 当事人来了,感谢大佬帮忙查找问题

  • 这密码是多弱?132次就爆破出来了。

  • @许较瘦 #5 DD完成后默认密码,没有马上改密码,先装了一波应用。才改密钥的

  • @colin-kj1 #6

    安全意识堪忧,第一改密码,第二改sshd_config,禁止密码登陆,添加密钥

    不过这次好歹没啥损失, xhj007

  • @许较瘦 #7 之前用的dd11的脚本是改端口号和密码来dd的,所以没太注意。这次改dd12全部默认的一下子老是了

你好啊,陌生人!

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

📈用户数目📈

目前论坛共有60503位seeker

🎉欢迎新用户🎉