每一个高手在成长路上,都需要与墙作充足的对抗。要么你成功,站在世界之颠,然后尽情汲取到顶级的知识;或者或被它打趴下,成为芸芸众生中的一人,然后对它习以为常。
我也不例外。
前不久,我刚在我的服务器上自行架好了自己的“梯子”。这正是从“梯子”开始的故事。
夜已经深了,我依然坐在电脑,思索着一件事:为什么突然之间,历来运行良好的 "梯子",突然就这么卡呢?莫非已经被 "墙" 发现并限制了?
我不甘心地想,这不可能,我隐藏的这么好,这么低调,不会是我。
我拿出手中最爱的工具:ping
.
开始了我的检测之旅。
100 packets transmitted, 40 received, 60% packet loss, time 10015ms
60% 丢包,这太夸张了,这样的网络环境简直比帝都的交通环境还差千倍。我在想。
试试另一个利器 traceroute
吧,只有第一跳是通的,F**K,果然是世界第一的局域网络,运营商也敢非法丢弃我的检测包,这个检测毫无收获。
但是,看着我的“梯子”在云层摇摇晃晃 (丢包),我就心生决意:不在对抗中成功,就在对抗中消亡。
正在无所措时,“梯子”所在的服务商给给我最爱的 Gmail 突然发送了一封至关重要的邮件,上面赫然写道:
Your xx Server, has exceeded the notification threshold (5) for outbound traffic rate by averaging 138.14 Mb/s for the last 2 hours
(你的梯子, 已经在连续两个小时内, 以超过 138.14 Mb/s 的平均速度, 连续发包)
啊,即将成为高手那种敏锐的第六感,让我觉得,我可能错怪 "墙" 了,我可能被黑了。
一阵饿意,让我清醒了不少,果然,有些高手发明的“轻断食”疗法非常有效,让我离高手更进了一步。
“我一定要把对手揪出来”,心里暗暗下决定。
ssh [email protected]
我开始连接到我的服务器,第一步,先从登录日志开始。
这是一个非常聪明的做法:
# who
root pts/2 2015-01-20 3:00 (xx.xx.xx.xx)
嗯,只有我一个人,并没有抓住黑客的现行。“我想他不会这么笨,让我当场拿住他”,心里暗想。
# last
root pts/2 li657-42.members Tue Jan 20 03:03 - 03:41 (00:38)
root pts/1 183.37.59.101 Tue Jan 20 02:54 - 05:12 (02:18)
root pts/0 li657-42.members Tue Jan 20 02:45 - 04:51 (02:05)
reboot system boot 3.18.1-x86_64-li Tue Jan 20 02:45 - 20:30 (17:45)
ruby pts/0 119.139.89.32 Sat Jan 17 01:03 - 01:03 (00:00)
ruby pts/0 119.139.88.22 Mon Jan 12 17:05 - 19:30 (02:24)
ruby pts/0 183.39.218.147 Sat Jan 10 16:31 - 16:33 (00:02)
ruby pts/0 183.39.218.147 Sat Jan 10 16:29 - 16:29 (00:00)
reboot system boot 3.18.1-x86_64-li Sat Jan 10 16:26 - 02:44 (9+10:17)
wtmp begins Sat Jan 10 16:26:21 2015
继续熟练地检查着有谁登录过系统,通过 ip138.com 检测着 IP 的来源。结果,全是我这里的 IP, 没有人!!!
莫非我弄错了?不是被黑了吗?
不行,继续看登录日志。
# grep 'sshd' /var/log/auth.log
Jan 18 18:56:42 localhost sshd[16157]: Failed password for invalid user user from 180.150.177.103 port 39118 ssh2
Jan 18 18:56:42 localhost sshd[16157]: Received disconnect from 180.150.177.103: 11: Bye Bye [preauth]
Jan 18 18:59:05 localhost sshd[16194]: Connection closed by 180.150.177.103 [preauth]
Jan 18 19:01:26 localhost sshd[16219]: Invalid user user from 180.150.177.103
Jan 18 19:01:26 localhost sshd[16219]: input_userauth_request: invalid user user [preauth]
Jan 18 19:01:26 localhost sshd[16219]: pam_unix(sshd:auth): check pass; user unknown
Jan 18 19:01:26 localhost sshd[16219]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=180.150.177.103
Jan 18 19:01:28 localhost sshd[16219]: Failed password for invalid user user from 180.150.177.103 port 45735 ssh2
Jan 18 19:01:29 localhost sshd[16219]: Received disconnect from 180.150.177.103: 11: Bye Bye [preauth]
Jan 18 19:03:52 localhost sshd[16248]: Invalid user user from 180.150.177.103
Jan 18 19:03:52 localhost sshd[16248]: input_userauth_request: invalid user user [preauth]
Jan 18 19:03:52 localhost sshd[16248]: pam_unix(sshd:auth): check pass; user unknown
Jan 18 19:03:52 localhost sshd[16248]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh r
...( 省略几万行 )
看到这么多 ssh 爆破登录日志,心里一阵凉意,果然在互联网上混,时刻要小心远方各种暗器。冷静一下,慢慢找找看。
花了几十分钟之后,除了各种用户名密码的登录失败外,并没有通过密码登录成功的日志,全无新的发现。
心里暗想,“对手也不弱嘛。”
不过,还有一个线索没有检查过:“目前服务器的流量仍然很高”。
是时候运用我手中的核心武器了。
目前思路还是很清晰的,要定位到底是哪个进程导致的高流量,然后通过它的行为,分析是否是黑客挂的马?
OK, 开始行动:
下载 iftop
, 打开系统的流量面板,10 秒之后,流量面板开始正确显示流量,我的流量峰值高达 100mb/s。调整一些命令参数,显示端口与 IP 信息。
iftop -nP
流量面板显示出是从我的服务器往外流出流量,先从 30157 端口开始往外发送,几秒之后,就会循环切到 30000 - 50000 之间的一个端口继续发。是 UDP 流量,我断言。
果然,再通过 netstat -anp
来检测打开端口情况,发现并没有 TCP 上的状态,确认了我的断言。
( UDP 流量是可以无状态的,可以快速切换,TCP 反之,可以通过工具抓到链接状态 )
但不幸的是,这两个工具并不能显示出来是哪个进程作的鬼。看来只有一个个看了。
ps aux
进程并不多,很快就看完了,有两个可疑进程:
ruby 5162 0.0 5.0 286128 102200 ? Sl 02:58 2:20 /usr/sbin/httpd -c ./init -d /home/ruby/lib/2
111 3033 0.0 5.0 1 2017 ? Sl 02:58 2:20 /tmp/freeBSD /tmp/freeBSD 1
第 1 点,我使用的是 nginx 而不是 apache,这里的 httpd 非常可疑。 第 2 点,freeBSD 明显是一个伪装,进程的权限也令人可疑。
至此,已经确认,我的服务器已经被黑了。接下来,是时候对决的时候了。
第 1 点的进程信息有一个目录非常可疑,在 /home/ruby/lib
, 这里是我的个人目录,怎么会出现在这里的参数里呢?
进去看看:cd /home/ruby/lib
# tree
.
├── 2
│ └── muhrc
├── config
├── cron.d
├── dir
├── f
├── h
├── h.c
├── init
├── inst
├── ips
├── log
├── mess
├── muhrc
├── restart
├── run
├── run2
├── servers
└── y
大吃一惊,第六感告诉我,这命名,这习惯,绝对是一个黑客作为,这不是我写的东西,仔细看看。
# cat y
#!/bin/sh
if test -r /home/ruby/lib/pid; then
pid=$(cat /home/ruby/lib/pid)
if $(kill -CHLD $pid >/dev/null 2>&1)
then
exit 0
fi
fi
cd /home/ruby/lib
killall -9 atd
./run &>/dev/null
Oh no,一个木马程序赫然在目,这是一个非常明显的反向连接木马:
只要你把服务器打开,它便会启动,并自动连接到黑客指定的服务器,报告黑客已经上线,然后等待指令。一旦有指令收到,便会用自己控制的权限运行对应的程序。非常可怕。
继续看,它的配置文件如下:
# cat muhrc
nickname = "Dan";
altnickname = "Dan";
username = "xxx";
realname = "dan e pe linode :)";
password = "xxx";
listenport = 41000;
awayreason = "mie";
servers {
"Tampa.FL.US.Undernet.org":6667,
"budapest.hu.eu.undernet.org":6667,
};
logging = false;
channels = "#olimpia";
connectcmd = "PRIVMSG [email protected] : login ";
away = "mie";
norestricted = true
这便是对手的反向连接的 IRC 地址,“这小子还真牛啊”,我心想,“他知道,这样的 IRC 地址我根本无法进一步追踪。”
现在,被黑的事实已经确认,却让我更担心的事情来了:
第一,他有没有控制到我的 root 权限
一旦被控制了 root 权限,系统就难于清理了,因为他可以在任意位置插入自己的木马,例如启动时,驱动,替换一个命令,隐藏在某个目录。
而且,可以手动清理日志,让你无法知道对方都干了什么,这样子,你就只能重装系统了。
第二,他是如何黑进我的服务器
不能知道对方是如何黑的,就无法制定有效的防御策略,这是非常可怕的。
不过,我知道,我离真相已经越来越近了。
继续翻看他的木马程序,发现一个非常有趣的东西: h.c
.
里面注释上写着:
psf -- Process Stack Faker (a.k.a. Fucker)
Coded by Stas; (C)opyLeft by SysD Destructive Labs, 1997-2003
Tested on: FreeBSD 4.3, Linux 2.4, NetBSD 1.5, Solaris 2.7
Compile with:
# gcc -O2 -o h h.c
# strip h
哈哈,psf 可翻译为进程堆栈伪造器。顾名思义,它是一个期骗 ps、top 命令的指令输出的一个小工具。
仔细查看它的说明,可以发现:
它的原理大概如下:
在 main 函数里面 (如下) 的参数,
int main(int argc, char *argv[])
可以继续调用以下 execv 接口,而 path 是可以与 main() 里的 agrv[0] 不一致,可以精心构造的,这样可以导致很多进程监控工具出现异常情况,显示出精心构造的参数。
int execv( const char *path, char *const argv[])
看到这个工具,我反而将之前的担扰全部放下了:用这点小伎俩来骗我,说明你很可能没有拿到 root 权限。
我仿佛已经听到对方叹气的声音,但又仿佛不是,好像有一点点笑声。
不管那么多了,下一步就要了他的命,我在想。
检查系统核心信息:
# 检查用户信息是否正常
cat /etc/passwd
# 检查系统文件是否被替换
find / -user 122 | xargs ls -l
一切显示正常,那么,系统很可能是没有被动到 root 的,是时候找出被黑的原因了。
从另一个进程的线索下手。
进程号 111, 非常特别,从刚才的用户信息可以看到,这个用户号属于:elasticsearch
。
原来如此,这个提示信息太重要了,此刻,我还记得之前为了安装一个网站应用,使用了 campo3
,安装了它的依赖 elasticsearch
,而之前 Rei 专门发邮件告诉过我:这货可能有远程执行漏洞。
不对啊,我已经打开了 ufw
防火墙了。
# ufw status
Status: inactive
什么,没有打开?心中一丝凉意侵入骨髓,我的服务器竟然在严酷的互联网环境上裸奔了这么久。查看操作日志,发现自从 1 月 8 号起,防火墙就没有打开过。
而且,是我亲自关闭了它。难怪,他的入侵成功日志正是 1 月 8 号。
此刻,这位黑客的入侵手段几乎已经真相大白:通过 elasticsearch
远程执行漏洞扫描工具扫进了我的服务器,再运行了提权工具发现了 /home/ruby/ 目录是可写的。
此时,他很聪明的伪装了它的木马,虽然没有拿到 root 权限,但仍然可以轻易的干掉我的博客进程 ( 虽然他没这么做 )。还可以随时让我的服务器成为它的帮凶,成为二次跳板,或者对无辜者发动 DDOS 攻击。
而我,也有一丝丝的侥幸,elasticsearch
并没有跑在 root 权限下,而是使用了 111
号用户,所以这次攻击他的最好收获也只能是,获得我 ruby 用户的权限,把我的服务器纳入他的肉鸡,为他以后更大规模的行动埋下伏笔。
需要补充点能量了,我在想,刚才煮好的泡面已经到了嘴边。
“如果我成为世界级黑客,我一定通过他的反向代理木马黑过去”,我一边吃着一起在想,“当务之急,还是先清理这些木马吧。”
第一步,关闭源头
先打开防火墙:ufw enable
。
清理 crontabs: crontab -l
, rm /var/spool/cron/crontabs/ruby
杀掉木马进程:kill pid
第二步,处理漏洞
按照 elasticsearch
官方处理建议,将默认的监听 IP 设定在 127.0.0.1, 关闭动态执行脚本能力:script.disable_dynamic: true
( 均在它的配置文件中完成 )
杀掉已被成功攻击的 elasticsearch
进程和子进程:kill -9 xxx
看来,离高手还差了不少,我心在想,以下措施要补救一下:
用户目录权限
之前,采用 useradd
的默认用户目录权限 644
, 允许任何用户进入,才导致这个黑客得以入侵成功。我把它关闭:chmod 700 /home/ruby
web 漏洞扫描
我需要在本地针对我的服务器做一些漏洞扫描。
防火墙保证开启
在 /etc/rc.local
加入:ufw enable
升级系统
说到这里,马上两条命令搞定:
apt-get update
apt-get upgrade
随着流量的正常回落,看到那我最心爱的 ping
上面完美地显示着
PING myblog.me (xx.xx.xx.xx): 56 data bytes
64 bytes from xx.xx.xx.xx: icmp_seq=0 ttl=52 time=84.207 ms
64 bytes from xx.xx.xx.xx: icmp_seq=1 ttl=52 time=80.165 ms
64 bytes from xx.xx.xx.xx: icmp_seq=2 ttl=52 time=83.242 ms
64 bytes from xx.xx.xx.xx: icmp_seq=3 ttl=52 time=86.241 ms
64 bytes from xx.xx.xx.xx: icmp_seq=4 ttl=52 time=86.799 ms
......
我的“梯子”又稳定地回来了。
我觉得,我离高手又近了一步。突然,显示器上开始缓慢的出现
64 bytes from xx.xx.xx.xx: icmp_seq=4 ttl=52 time=86.799 ms
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2
Request timeout for icmp_seq 3
......
我知道,对方又回来了。
本文首发于:WinDy's Blog