linux scrapy 定时任务_Linux 定时任务的攻/防/查

上一期说这期要讲 Crontab。想了一下其实还有其他的定时任务可以放着一块讲,所以新增了一些篇幅。那么自然而然呢,这一期也就延后了一丢丢,真滴是一丢丢...技术人的鸽,哪里能叫咕呢?

628ed65f6c03caa4c8f0b286ce2a250c.png

e2af57e6beb4c6df14961377ade39412.png

在 Linux 一说“定时任务”,想必大家第一反应都是 Crontab。其实定时任务不止有 Crontab,还有 Anacronat。就算是大家最为熟悉的 crontab,其实还是有很多细节的知识的。比如各位可以问问自己,若攻击者插入了一条恶意的 crontab,该怎么找出来呢?或者说,如何完整地检查一下服务器的 crontab 呢?大家的第一反应可能是 crontab -l,但其实这样只能检查很有限的一部分740fb02ce16e5a2df095aad1bfb91413.png本文以 centos 为例,介绍一下 Linux 定时任务的攻/防/查。

Crontab

大多数人都用过 Crontab:crontab -e / -l,所以这里就不介绍了,也不赘述使用方式了。

要想完整的列出 crontab,最好还是从 crontab 保存的定时任务文件入手。

Crontab 相关的文件

Crontab 相关的文件分别在 /etc/var/spool/cron/ 下:

  1. /etc/
    1. /etc/cron.allow: 相当于白名单,限制类配置,不在这里面的用户不能使用 crontab
    2. /etc/cron.deny: 相当于黑名单,限制类配置,在这里面的用户不能使用 crontab
    3. /etc/crontab: 系统级别的定时任务配置,可以理解为大家一起用的定时任务,所有权是系统而不是特定的某用户
    4. /etc/cron.d/: 这个文件夹下的配置同 /etc/crontab。假如你有个定时任务不想直接写到 /etc/crontab里,那么你可以选择新建一个文件,放在 /etc/cron.d/ 里面(无需其他配置,直接生效)。
      1. /etc/cron.d/0hourly: 自带的,其实就是用 run-parts 去执行 /etc/cron.hourly 下面的脚本
      2. ...(可能有其他用户把定时任务放在这下面)
    5. /etc/cron.hourly/: 被 /etc/cron.d/0hourly 执行。里面是可执行文件或者 shell 脚本。
      1. /etc/cron.hourly/0anacronanacron 下面会讲
    6. /etc/cron.daily/etc/cron.weekly/etc/cron.monthly: 看起来和 crontab 有关系?其实是 anacron的!下面会讲
  2. /var/spool/cron/: 存放每个用户的 crontab,所有权是特定的用户(注意与 /etc/crontab 对比)。这个就是我们在用 crontab -e 的时候创建/编辑的文件,所以文件名就是用户名,并且执行的时候是用文件名(即用户名)的权限来执行的,例如你在下面建了一个名叫 Tr0y的文件,则会以Tr0y的身份去执行这个文件里的定时任务。需要注意的是,如果你在这个目录下强行创建了一个以不存在的用户名为命名的文件,例如 test,但是你又没有这个用户的话,test 里面的定时任务是不会执行的。另一个需要注意的是,/var/spool/cron/ 的所有权是 root,所以普通用户是没办法直接在下面创建文件的,只能加 sudo 或者通过 crontab -e
    1. ...(各个用户的 crontab)

注意,/etc/cron.allow 的优先级比 /etc/cron.deny 要高,所以配置只需要选择一种来限制即可。一般来说,系统的用户相对可靠,故默认保留的是 /etc/cron.deny,且内容为空,这样所有人都能用 crontab。如果这两个限制文件都不存在,那么只有 root 才能使用 crontab。

最后需要注意的是,cron 是不会递归文件夹的,所以你在 /etc/cron.d//var/spool/cron/ 下面建文件夹,再在里面放配置文件是没用的。为什么要特别提到这一点?因为我见过有攻击者这么干过...a48b1bb2f86b3a75a5949d79fb96917f.png

防御建议

  1. 使用 /etc/cron.allow 来指定可使用 crontab 的用户(最好不要使用黑名单的/etc/cron.deny)。需要注意的是,此文件一定要是 root 所有
  2. 检查 crontab 的时候,分别检查:/etc/crontab/etc/cron.d/*/var/spool/cron/*
  3. 检查是否有除了 /etc/cron.hourly/0anacron 之外的 anacron 定时任务(下面会提)

Anacron

Anacron 可能大家用的少一点,所以会说的多一些。

它与 Crontab 最大的不同在于,它会去执行那些落下的定时任务。举个例子,假如你设定了一个 Crontab 定时任务,在每周六晚上 6 点执行。但是正好周六晚上 5 点到 7 点停电了,那么这个定时任务相当于这一轮就没有执行。但是如果你用的是 Anacron,它会去检查并执行那些没有执行过的定时任务。实际上,Anacron 是每个小时被 crond(Crontab 服务)执行一次,然后 Anacron 再去检测相关的定时任务有没有被执行,如果有超期没被执行的工作,就执行该定时任务。

Anacron 其实仅仅是一个程序,不像 Crontab 那样利用 crond 服务执行。之前在 Crontab 里提到过,有个自带的每一个小时执行一次的定时任务集合:/etc/cron.d/0hourly,而这个定时任务其实就是用 run-parts 去执行 /etc/cron.hourly 下面的脚本,这里面自带一个 0anacron,其实就是这一节提到的 Anacron。所以 Anacron 其实是依托于 Crontab 去定时执行的。0anacron 如下:

#!/bin/sh
# Check whether 0anacron was run today already
if test -r /var/spool/anacron/cron.daily; then
day=`cat /var/spool/anacron/cron.daily`
fi
if [ `date +%Y%m%d` = "$day" ]; then
exit 0;
fi

# --- 上面这部分就是我说的检测定时任务是否执行过的逻辑 ---

# Do not run jobs when on battery power
if test -x /usr/bin/on_ac_power; then
/usr/bin/on_ac_power >/dev/null 2>&1
if test $? -eq 1; then
exit 0
fi
fi
/usr/sbin/anacron -s

# 所以这个脚本其实执行的就是 `anacron -s`...

各位可能会觉得很奇怪,为啥这个名字最前面要加个 0。根据网上的说法,0 开头的定时任务会排在最前面执行,这样的话,就避免了有些 Crontab 定时任务执行过之后,Anacron 误以为 Crontab 没执行,导致重复执行某些定时任务。包括命令之前加上 nice 让它优先获得 cpu 以便执行,也是出于这个目的64d4ad1840db307c3421332cf263f6b3.png

Anacron 的相关文件

  1. /etc/anacrontab: 与 /etc/crontab 类似,自带,通过 run-parts 执行 /etc/cron.daily/etc/cron.weekly/etc/cron.monthly
  2. /var/spool/anacron/: 记录上面几个的执行时间,内容就是年月日
    1. /var/spool/anacron/cron.daily
    2. /var/spool/anacron/cron.monthly
    3. /var/spool/anacron/cron.weekly
  3. anacrontab 可以通过 -t 参数指定 /etc/anacrontab 的位置,默认就是 /etc/anacrontab

简单解释一下 /etc/anacrontab 的内容吧:

SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
RANDOM_DELAY=45 # 执行之前随机延迟时间(分钟,可分散服务器的压力)
START_HOURS_RANGE=3-22 # 允许执行命令的时间段(这里是 3 点 - 22 点才能执行)

1 5 cron.daily nice run-parts /etc/cron.daily

# 1: 每隔多久执行(天)
# 5: 固定延迟时间(分钟)
# cron.daily: 定时任务名称,随便设置,主要是看 log (/var/log/cron 的时候可能有用)
# nice run-parts /etc/cron.daily: 定时任务的核心 —— 要执行的命令

/etc/cron.d/0hourly 挺像的,同时名字最前面加 0 这个逻辑也是一样的。

cron.daily 为例,对照上面这个配置,总结一下 Anacron 的运行流程:

  1. crond 读取 /etc/crontab/var/spool/cron/*/etc/cron.d/*,根据设定的时间执行
  2. 执行到 /etc/cron.d/0hourly 的时候,执行 /etc/cron.hourly/ 下的所有可执行文件,其中就有 0anacron
  3. 0anacron 执行 anacron
  4. anacron 读取 /etc/anacrontab,它指定了 cron.daily 执行间隔为 1 天
  5. /var/spool/anacron/cron.daily 取出最近一次执行 anacron 的时间
  6. 比较当前时间与上一步获得的时间,若相差 1 天以上 (含 1 天),则准备执行指定的定时任务。
  7. 根据 /etc/anacrontab 的设置,执行之前要先延时 5 分钟 + n 分钟(n 为不超过 45 的随机数)
  8. 延时到点之后,开始执行指定的命令,即 nice run-parts /etc/cron.daily
  9. 执行完毕,结束

最后,anacrontab 仅能用 root 权限配置。

防御建议

anacrontab 的执行比较佛系,最快也就是一天执行一次(除非加上了-f,强制每轮检查都执行),所以恶意软件通常不想用这个去做持久化。不过也不好说,谁让它比 crontab 隐蔽呢?340a28241fe39235aec0fc663db4f535.png

  1. 检查 /etc/anacrontab 下是否有疑似恶意的定时任务
  2. 检查 /etc/cron.hourly/0anacron 是否利用-t自定义了 anacrontab 定时任务文件位置,如果有也要检查这个自定义的文件。

at

at 依赖于 atd 服务执行,这点与 crontab 有点像,但现在似乎不是默认启用 atd 的,所以可能需要手动启动(systemctl start atd)。它与前两个最大的区别在于 at 是一次性的,设定完之后只会运行一次

at 的相关文件

  1. /etc/at.allow: 相当于白名单,限制类配置,不在这里面的用户不能使用 at
  2. /etc/at.deny: 相当于黑名单,限制类配置,在这里面的用户不能使用 at
  3. /var/spool/at/: 保存定时任务的文件夹。下面用特定格式的文件名存放定时任务详情,包括命令、环境变量、设定定时任务时的路径等。
    1. /var/spool/at/spool: 据说是保存输出的文件夹...至于是什么输出、什么时候会输出到这里就不得而知了...
    2. 示例:a000030196c020。这个文件名的格式暂时没找到资料,不过经过我的测试,格式应该为,a(固定)+00011(任务每加一个这里要+1)+从 1970-01-01 08:00:00 至 任务执行时间 的分钟数(8 位,位数不够在前面补 0) (注意这里面计算都是十六进制的)

上面的两个限制文件个 crontab 类似,也是 allow 的优先级比 deny 要高,如果这两个限制文件都不存在,那么只有 root 才能使用 at。

当然,你也可以不用 at 来新建定时任务,只要往 /var/spool/at/ 下面新建文件,注意权限要有 x,且得是 root 才能这么创建,至于文件名,一定要按照上面的规则才能被识别。示例,若我们想建一个在 2030-01-01 08:00:00 执行的定时任务。先计算一下时间差:

In [27]: import datetime

In [28]: delta = datetime.datetime.strptime('2030-01-01 08:00:00', "%Y-%m-%d %H:%M:%S") - datetime.datetime.strptime('1970-01-01 0
...: 8:00:00', "%Y-%m-%d %H:%M:%S")

In [29]: hex(delta.days * 24 * 60) # 转分钟
Out[29]: '0x1e187e0'

补齐至 8 位:01e187e0

所以这个定时任务的格式应该为 a+00012(上一个任务+1)+01e187e0(时间差) = a0001201e187e0

➜  at atq
➜ at vim a0001201e187e0
➜ at atq
18 Tue Jan 1 08:00:00 2030 a root

各位如果比较敏感的话,就会想到 8 位的 hex,会不会出现类似千年虫的 bug 呢?0xffffffff = 4294967295 年,43 亿年,嗯,各位是等不到了67544f5312a3c36da3d17d990683a6c0.png

最后有 3 点要提一下:

  1. 如果 at 定时任务执行没有成功,似乎会变成=开头的定时任务(原来是a开头的)
  2. 执行时间在过去的定时任务是不会被执行的
  3. 在直接写 at 定时任务的时候,要注意开头要有这三行:
#!/bin/sh            # shell
# atrun uid=0 gid=0 # 应该是表明计划任务的拥有者的权限,未考证
# mail root 0 # 触发发邮件的逻辑时,收件人是谁
  1. 与 at 相关的还有一个 batch 命令,通过它设定的 at 定时任务,只有在 cpu 负载小于 0.8 的时候才会运行,且文件名则会以 b 开头。其实原理都是一样的,batch 也是用 at 来配置定时任务的:
➜  at echo 'echo <0001f382> > /dev/pts/8' | batch && ls
job 32 at Mon Aug 3 17:35:00 2020
b000200195ff5f spool

at 的可读性还是很好的,例如你可以给自己发一个生日祝福:echo 'echo <0001f382> > /dev/pts/8' | at 00:00 September 7

➜  ~ echo 'echo <0001f382> > /dev/pts/8' | at 00:00 September 7
job 1 at Mon Aug 3 14:02:00 2020
➜ ~ atq
1 Mon Sep 7 00:00:00 2020 a root
➜ ~ ls /var/spool/at/
a000010195fe8a spool
➜ ~ cat /var/spool/at/a000010195fe8a
#!/bin/sh
# atrun uid=0 gid=0
# mail root 0
...
cd /root || {
echo 'Execution directory inaccessible' >&2
exit 1
}
...
echo ? > /dev/pts/8
...

等到 9 月 7 号,你就会收到你自己给自己发的 ? 了,再也不用担心没人送祝福啦(前提是你的 tty 没变)。等一下,怎么这么凄凉呢...  67544f5312a3c36da3d17d990683a6c0.png

防御建议

如果说选择 anacrontab 的恶意软件较少,那么选择 at 的恶意软件就更少了,同样也是比较隐蔽,甚至比 anacrontab 要更加隐蔽。

  1. 使用 /etc/at.allow 来指定可使用 at 的用户(最好不要使用黑名单的/etc/at.deny)。需要注意的是,此文件一定要是 root 所有
  2. 检查 /var/spool/at/ 下是否有可疑的定时任务

前段时间把那篇

《WebShell 过狗没意思,我们要过人!》

投到 Freebuf 去了

拿了几百的饭钱

今天通知说上了 7 月热门文章

cf8f23ff72495a333c08df9cdce00725.png

还是挺开心的

7b7243225a753055cfae76f8443d08ca.png

我其实挺喜欢与人讨论技术

可惜我的公众号是新开的

没有留言板的功能

真是一大遗憾啊...

本期开始封面会换成我自己拍摄的照片

初期可能有点辣眼睛...

不过我相信会变好的

下期会讲一下前段时间的 scp 远程代码执行

以及附带一些思考

至于下一期是什么时候嘛

...

...

...

反正没人催更...

咕咕咕

340a28241fe39235aec0fc663db4f535.png

这期话怎么这么多

51e9c9af5f31f6f2a6d3877d25c37048.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值