分享 高手对决 -- 博客服务器被黑的故事

lyfi2003 · 发布于 2015年01月21日 · 最后由 xiao__liang 回复于 2016年05月06日 · 15245 次阅读
121
本帖已被设为精华帖!

每一个高手在成长路上, 都需要与墙作充足的对抗. 要么你成功, 站在世界之颠, 然后尽情汲取到顶级的知识; 或者或被它打趴下, 成为芸芸众生中的一人, 然后对它习以为常.

我也不例外.

前不久, 我刚在我的服务器上自行架好了自己的 "梯子". 这正是从 "梯子" 开始的故事.

开幕

夜已经深了, 我依然坐在电脑, 思索着一件事: 为什么突然之间, 历来运行良好的 "梯子", 突然就这么卡呢? 莫非已经被 "墙" 发现并限制了?

我不甘心地想, 这不可能, 我隐藏的这么好, 这么低调, 不会是我.

我拿出手中最爱的工具: 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 root@myblog.me

我开始连接到我的服务器, 第一步, 先从登录日志开始.

这是一个非常聪明的做法:

# 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 x@channels.undernet.org : login ";
away = "mie";
norestricted = true

这便是对手的反向连接的 IRC 地址, "这小子还真牛啊", 我心想, "他知道, 这样的 IRC 地址我根本无法进一步追踪."

现在, 被黑的事实已经确认, 却让我更担心的事情来了:

  1. 他有没有控制到我的 root 权限

    一旦被控制了 root 权限, 系统就难于清理了, 因为他可以在任意位置插入自己的木马, 例如启动时, 驱动, 替换一个命令, 隐藏在某个目录.

    而且, 可以手动清理日志, 让你无法知道对方都干了什么, 这样子, 你就只能重装系统了.

  2. 他是如何黑进我的服务器

    不能知道对方是如何黑的, 就无法制定有效的防御策略, 这是非常可怕的.

不过, 我知道, 我离真相已经越来越近了.

继续翻看他的木马程序, 发现一个非常有趣的东西: 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 命令的指令输出的一个小工具.

仔细查看它的说明, 可以发现:

  1. 无须 root 权限, 即可让你指定的进程伪造成任何一个进程名字.
  2. 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.

原来如此, 这个提示信息太重要了, 此刻, 我还记得之前为了安装 railsgirlschina.com, 使用了 campo3, 安装了它的依赖 elasticsearch, 而之前 Rei 专门发邮件告诉过我: 这货可能有远程执行漏洞.

不对啊, 我已经打开了 ufw 防火墙了.

# ufw status
Status: inactive

什么, 没有打开? 心中一丝凉意侵入骨髓, 我的服务器竟然在严酷的互联网环境上裸奔了这么久. 查看操作日志, 发现自从 1 月 8 号起, 防火墙就没有打开过.

而且, 是我亲自关闭了它. 难怪, 他的入侵成功日志正是 1 月 8 号.

此刻, 这位黑客的入侵手段几乎已经真相大白: 通过 elasticsearch 远程执行漏洞扫描工具扫进了我的服务器, 再运行了提权工具发现了 /home/ruby/ 目录是可写的.

此时, 他很聪明的伪装了它的木马, 虽然没有拿到 root 权限, 但仍然可以轻易的干掉我的博客进程( 虽然他没这么做 ). 还可以随时让我的服务器成为它的帮凶, 成为二次跳板, 或者对无辜者发动 DDOS 攻击.

而我, 也有一丝丝的侥幸, elasticsearch 并没有跑在 root 权限下, 而是使用了 111 号用户, 所以这次攻击他的最好收获也只能是, 获得我 ruby 用户的权限, 把我的服务器纳入他的肉鸡, 为他以后更大规模的行动埋下伏笔.

需要补充点能量了, 我在想, 刚才煮好的泡面已经到了嘴边.

"如果我成为世界级黑客, 我一定通过他的反向代理木马黑过去", 我一边吃着一起在想, "当务之急, 还是先清理这些木马吧."

清理

  1. 关闭源头

    先打开防火墙: ufw enable.

    清理 crontabs: crontab -l, rm /var/spool/cron/crontabs/ruby

    杀掉木马进程: kill pid

  2. 处理漏洞

    按照 elasticsearch 官方处理建议, 将默认的监听 IP 设定在 127.0.0.1, 关闭动态执行脚本能力: script.disable_dynamic: true ( 均在它的配置文件中完成 )

    杀掉已被成功攻击的 elasticsearch 进程和子进程: kill -9 xxx

加固

看来, 离高手还差了不少, 我心在想, 以下措施要补救一下:

  1. 用户目录权限

    之前, 采用 useradd 的默认用户目录权限 644, 允许任何用户进入, 才导致这个黑客得以入侵成功. 我把它关闭: chmod 700 /home/ruby

  2. web 漏洞扫描

    我需要在本地针对我的服务器做一些漏洞扫描.

  3. 防火墙保证开启

    /etc/rc.local 加入: ufw enable

  4. 升级系统

    说到这里, 马上两条命令搞定:

    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

共收到 62 条回复
1

我把防火墙规则写到 Linode 的 StackScripts,避免忘了设置。

# firewall
ufw allow ssh
ufw allow http
ufw allow https
ufw logging on
ufw enable
3873

我靠,我当时也出过这个问题…就是莫名奇妙流量爆了。linode 服务器,完全没理…

1573

非常精彩,其实文中提到的命令工具我们多少都碰过,但基本都是“正常状态”下的使用,而像这样从头到尾分析对抗攻击的就很少能遇到并亲自实践了。楼主的文让人有身临其境之感,不赞不行啊~

121

#1楼 @Rei 嗯, 是个好主意:)

96

虽然是虚构,但是高手怎么会害怕SSH暴破呢……补救措施第0条,关你密码登录使用密钥

5433

:plus1:

121

#6楼 @ninehills 部分虚构, 让你误解了. 不过这个故事其实跟 ssh 暴破没任何关系.

6253

受教了 遇到相同问题

10784

赞~~身临其境的感觉

501

:thumbsup:

2492

Cool.

A87c18

先赞后看。

8089

我也是linode,遇到过同样的问题,解决方案:数据备份,销毁,Rebuild.

1286

学习了

12224

#4楼 @nightire 直接把服务器弄成蜜罐,天天 "身临其境" 😄

2474

囧。。。居然是虚构……

27

lz 赶紧连载一部小说吧,好期待!

4584

1、可以用个ssh-guard防扫,用证书认证的话就不怕被扫了 2、感觉飞哥写这种文有点赞,当然也有点夸张 😃

2973

乐在其中。

973

看了一场电影.

959

虽然有些看不懂,但是很赞! #8楼 @lyfi2003

96

也是因为 @Rei 的 campo 中过一次招,但是并不知道为什么,只是能过开启iptables然后就没事了。

4791

非常棒,顶一个

3698

学到一个iftop :)

96

#8楼 @lyfi2003 不过我对这个解决方法不太认可。

被黑客入侵后,保留数据重做系统,乃是最稳妥的解决办法。重做系统的成本在你选择了合适的部署方式后其实非常小。

16935

弓虽

9162

遇到了一模一样的问题……lz解决了我所有疑惑!

5917

精彩

360

Mark,学习~~

4499

我来改变成微电影剧本: 镜头一,主角面无表情盯着屏幕; 镜头二,主角皱眉盯着屏幕; 镜头三,主角惊恐盯着屏幕; 镜头四,主角飞快敲击键盘,继续面无表情盯着屏幕; 镜头五,主角微笑盯着屏幕; 镜头六,黑客冷笑盯着屏幕; 镜头七,主角拿起旁边的泡面,发现面还没糊。 全剧,终! 哈哈~~~~

136

#27楼 @ninehills 嗯 在不确定系统还有什么地方被黑的时候,重做系统是最快的。某次就见过一个服务器,ls, cd 之类的命令全都被替换了,还有N多地方都藏了木马…我就果断重装了…

115

发生过类似的事情, 有一次偶然 iftop 之后看到 100+M 的数据, 我就知道被黑了, 然后找到奇怪的进程, 杀掉, 然后在 ~ 目录发现奇怪的文件夹, 删掉, 然后改了登陆密码, 然后就好了, 没有挖的那么深.

看了你的分享, 我觉得我是不是根本就没有清除干净?

121

#27楼 @ninehills 作为 "高手" 怎能轻易服输 😄 , 不能老使用大招.

96

真的跟看电影一样。。。

14935

赞一个👍高手

13116

为什么楼主每次文章都喜欢多处发。。。我只是好奇而已

1453

啊哈哈 yafei

10775

好赞啊!

341

非常不错啊,感觉讲了一个非常精彩的故事。我曾经也碰到过类似的事情,因为时间关系,并没有像楼主那样去刨根问底,根源大概也是找到了,但是没有很好的解决。最终的方案因为是使用了ucloud,主机数据重新迁移了下,然后ip动态绑定解决的。那一次对方应该是通过tomcat漏洞进来的,因为偷懒,tomcat默认配置,端口没有修改,站点管理也没有关闭,可能是这么进来的。然后在/etc/init.d/下会植入一个进程,杀掉了还会重新启动。

有些命令行工具学习了。

15245

非常赞,顶一个!寓教学于玩乐,看的刺激又学到不少干货.

818

故事类的技术文章易懂易看,赞。

96

赞!

296

赞,看的心惊肉跳!

579

现在伟大的墙真的要拆梯子了,何解?

1364

感觉又在看《电脑爱好者》或者《网友世界》,,,

5023

赞啊,看得鸡皮疙瘩都起来了。。。

14206

这是《谍影重重》的节奏吗!嘿嘿,马特达蒙先生,写得不错!浅显易懂!期待下一集!

2948

不要设置ssh 的端口是 22 有空多留意 /var/log/auth.log

2968

厉害,学习了

96

我的服务器也被入侵了. 但是我并没有安装es, 只是安装了nginx. 有人黑进了我的服务器, 他用www账户重新启动了一个sshd进程, 并开在6667端口上. 还启动了crond, 以及httpd这类进程.

黑客被发现是因为在自动扫描同网段ip的时候,被digitalocean给探测到, 从而屏蔽了.

我好奇的是, 他们是借助什么漏洞入侵的. 黑客用的www用户身份启动的进程, 由此可以发现黑客并没有root成功, 但是我只启动了nginx, 假设了反向代理访问slideshare. 这样都被入侵, 难道是因为nginx最近有安全漏洞?

121

#54楼 @seveniruby nginx 有漏洞也是有可能的, 具体的要查看一下版本号, 再检查一下它的日志.

另外, nginx 出问题可能性很小, 极有可能是背后的进程有漏洞导致.

96

#55楼 @lyfi2003 我追查了我的服务器, 我发现黑客的步骤是用一个ip暴力破解很多次, 一直在尝试www以及www开头的用户的口令. 然后在5000次之后, 某个ip直接用www直接登录了我的系统.

我现在怀疑这个www账户的密码规则可能是容易被破解的. 这个账户是一些服务自动创建的. 有可能是密码规则太低. 检查了下/etc/passwd 竟然发现这www用户是可以登录系统的.

15112

挺精彩~~~

554

思维条理

15999

请问什么样的梯子比较不容易被发现

9572

有意思。nice job。

1638

我的 VPS 今天也被黑了,郁闷。。。

25910

哈哈,第一次读这么有趣的技术文,真的是全程兴致盎然啊,谢谢楼主,

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册