Linux下crontab持久化后门:从发现到清除的完整指南
1. 从攻击面看系统脆弱性1.1 为什么是 crontab做系统运维或安全巡检的人对 crontab 都不陌生。它是 Linux/Unix 系统里用来定时执行任务的机制系统自带的周期性调度器支持用户级和系统级的任务配置。绝大多数服务器上都在跑也正因为它是系统标配攻击者拿到目标机器权限后第一时间就会翻 crontab 相关路径看看有没有可以利用的空间。说到“持久化”安全圈的人最关心的就是一件事攻击者能不能在我清理完入口之后还能回来。反弹 shell 本身只是在那一瞬间建立一个连接断了就没了。要想让这个连接反复出现就得有东西定时把它拉起来。crontab 恰好就是这种“定时拉起”的最佳载体因为它是由系统守护进程负责调度的不需要用户登录也不需要保持当前终端会话只要时间一到就会执行。这个特性本身是系统的正常功能设计初衷是为了让管理员可以定期执行备份、清理日志、同步数据这类任务。但攻击者不会只看到“正常功能”这层含义他们会反过来想如果我把自己的命令写进去系统就会按时帮我执行。这就是典型的“合法工具滥用”思路也是为什么单纯靠封 IP、杀进程很难彻底解决问题——因为你杀掉的是攻击的结果而不是攻击的入口。1.2 攻击者为什么钟爱持久化有实际对抗经验的人应该都遇到过这种情况某台服务器被入侵了你第一时间断了外连、清了临时文件、杀了可疑进程以为处理干净了。结果第二天一查又出现了同样的连接而且来源 IP 还换了。这就是持久化的问题。攻击者花精力拿下一台机器并不只是为了“看一眼”他们需要长期控制用来做跳板、挖矿、挂马或者持续窃取数据。如果每次进来都要重新走一遍漏洞利用流程成本高不说漏洞迟早会被修复。所以他们会想尽办法留下后路crontab 只是其中一条路还有自启动项、计划任务、SSH 授权密钥、动态链接库劫持等等。理解这些手法的关键不在于背下几条命令而在于建立一种思维模式凡是系统提供“周期性执行”“开机自启”“服务托管”这类能力的机制都有被攻击者盯上的可能。把这个思路捋清楚了才能明白审计和加固的真正重点在哪里而不是把安全配置做成形式主义。2. 常见的计划任务持久化路径2.1 系统级与用户级配置点Linux 下计划任务的配置文件分布在几个固定位置这也是每次安全巡检必须先看的地方。系统级的任务配置一般集中在/etc/crontab和/etc/cron.d/目录。/etc/crontab是系统主配置文件里面通常写着每小时、每天、每周、每月的默认任务/etc/cron.d/目录下可以放独立的任务文件很多软件包会把自带的定时任务丢在这里。还有一些目录需要注意/etc/cron.hourly/、/etc/cron.daily/、/etc/cron.weekly/、/etc/cron.monthly/这些目录里的脚本会被 run-parts 机制周期性执行所以只要往这些目录里丢一个可执行脚本就等于注册了一个定时任务。用户级的任务就分散在每个用户的 spool 目录下通常是/var/spool/cron/或者/var/spool/cron/crontabs/文件名就是用户名。这里有个容易被忽略的细节每个用户都可以用crontab -e编辑自己的任务列表而且不需要有 root 权限。这也就意味着哪怕只是一个低权限用户被攻破攻击者也能在该用户的任务列表里做手脚之后用这个用户的身份定时执行自己的东西。安全审计的时候很多人只看系统级配置忽略了用户级。实际上攻击者拿到权限的第一反应往往是先看看当前用户是谁、能写哪些文件而不是直接去找 root 的配置。因为一旦动了系统级的 crontab特征太明显反而是用户级的内容不太容易被注意到。2.2 攻击者在配置里通常会写什么这个问题需要从“如何达到持久控制”这个目标来倒推。攻击者要的不是在服务器上跑一条一次性的命令而是要建立一个能够反复建立连接的通道。所以他们在 crontab 里写的往往不是单一的命令而是一个“拉起来就连接”的完整逻辑。常见的写法是把反弹 shell 的命令直接写在任务里比如设置成每隔几分钟执行一次。还有的会先下载一个脚本到本地任务里只写执行脚本这一条命令这样升级或者换 IP 的时候只需要改远端文件crontab 本身不用动隐蔽性更好。也有一些会在任务里加上一些干扰性的前缀比如看起来像是正常的日志清理命令中间夹带自己的逻辑目的就是让人在快速浏览时一眼看不出问题。时间间隔的选择也有讲究。设得太频繁容易被发现设得太久又会让攻击者等太久才拿到连接。实践中比较常见的是一到五分钟一次既能保证连接断开后很快恢复又不会因为执行次数太多造成明显的资源占用。当然这套东西如果遇到了好的监控和告警其实撑不了太久这就是为什么防守方只要认真查总能抓住蛛丝马迹。2.3 为什么单纯重启解决不了把问题想得再深一层为什么很多受害者以为重启服务器就没事了因为反弹连接是内存里的东西进程一被杀、网络一断开表面上确实“干净”了。但只要 crontab 里的任务还在磁盘上系统一启动调度器就会重新开始运行到点之后照样把命令拉起来。这就是“持久化”和普通入侵最大的区别。普通入侵是一次性的你杀进程、清文件、补漏洞就结束了。持久化后门是把自己嵌入到系统的运行机制里你清掉的只是一个执行结果而不是触发机制本身。所以做应急响应的时候我个人的习惯是任何处理动作做完之后都要把计划任务、自启动项、登录配置这类持续性入口全部复查一遍缺了这个环节前面的清理很可能都是白费功夫。3. 识别与排查从蛛丝马迹到实锤3.1 配置审计的完整路径排查 crontab 持久化核心原则就一句话把你该看的地方全都看一遍不要因为“看起来正常”就跳过。下面这条排查路径是我在实际工作中会走的每一步都有具体的命令或者做法。第一步看系统级配置。需要检查的文件包括/etc/crontab、/etc/cron.d/下的所有文件以及/etc/cron.hourly/等周期目录里的内容。/etc/crontab可以直接用文本方式查看如果文件里出现了非默认的任务要仔细确认是不是管理员自己加的。/etc/cron.d/目录可以用通配符列出所有文件来逐个查看重点观察有没有最近修改过的、文件名特别奇怪的条目。第二步看用户级任务。用crontab -l可以列出当前用户的任务但要做全量排查得把所有系统用户的 spool 文件都翻一遍。遍历一下/var/spool/cron/目录看看里面有哪些文件再逐个查看内容。有些发行版用户 spool 目录路径可能不太一样需要根据实际情况调整但大方向是一样的。第三步看/etc/anacrontab。这个文件在某些系统上也可能成为持久化的落脚点虽然不如 crontab 常见但审计时值得扫一眼。第四步看日志。/var/log/cron里记录着 cron 守护进程实际执行的每条任务如果发现某条任务频繁执行但没有对应的合法来源就需要顺着这个线索去排查。日志量大是常态建议结合时间点去过滤比如对应服务器出现可疑外连的时间段。把这些步骤走完基本能把 crontab 相关的持久化入口都过一遍。这里要特别提醒一点很多排查只做了前三步把日志环节跳过了。但日志往往是最能说明问题的地方因为配置可以伪造执行记录骗不了人。3.2 从进程和网络反向定位计划任务只是个触发机制真正暴露行踪的是任务执行之后产生的进程和网络连接。所以排查的时候不能只看配置还得把“执行结果”也纳入视野。先看进程。定时任务如果反弹 shell 成功目标机器上就会有一个对外发起连接的进程这个进程可能是 bash、python、perl、nc 或者其他常见解释器。用ps aux或者top看的时候要重点关注那些用户看起来不对、父进程是 cron 的进程。正常情况下普通用户的 cron 任务很少会持续驻留如果看到父进程 PID 是 cron 且一直在跑基本可以确定有问题。再看网络连接。外连的反弹 shell 一定会在网络层留下痕迹查的时候用ss -antp或netstat -antp看所有对外连接特别关注那些发往非标准端口、远端地址不在已知业务列表里的连接。有些攻击者会用 53 端口或者 80 端口来伪装流量所以不能只看端口是不是常用服务还要看连接的目标 IP 和你业务的实际访问清单是否匹配。还有一个容易被忽略的点crontab 里的任务如果是下载脚本再执行那脚本下载下来会落在磁盘上。这类文件通常会刻意伪装成日志文件、临时文件藏在/tmp、/var/tmp、/dev/shm或者应用目录里。查的时候可以按时间去排序找出被修改过的可执行文件和脚本。3.3 让排查结果可验证排查完成不等于工作完成还要让结果可验证。我通常会把检查过的位置、看到的关键字段、发现的可疑点都记录下来形成一份时间线方便后续回溯。这样做有两个好处一是如果问题反复出现可以拿新的记录和历史记录对比判断是没清干净还是重新进来的二是给管理员的日常巡检留下一份基线后续再查的时候直接对比基线找差异效率比每次都从头看要高很多。4. 实操记录一次完整的排查与清理过程4.1 现象描述某台业务服务器近期出现异常对外网络连接明显变多而且系统负载偶尔会突然升高但业务流量并没有对应增长。运维同事先用top看到有几个奇怪的进程PID 一直在变化命令行的可执行文件名看起来像系统命令但放到对应的系统路径下却找不到文件。这时候基本可以判断这台机器大概率被种了东西而且不是一次性的是有机制在反复拉起进程。4.2 排查动作和执行记录按前面说了的思路第一步先看网络连接定位问题进程。执行ss -antp之后发现有一个进程在向某个非业务网段的 IP 发起外连走的端口是 8443。这个端口在业务上没有任何对应关系基本可以划入可疑范围。顺着 PID 查进程详情看到进程可执行文件路径在一个临时目录下这就不是正常二进制该待的地方。接着查这个进程的父进程发现它的父进程 PID 对应的恰好是 cron说明这个进程是由计划任务拉起来的。有了这个线索就直接去翻 crontab 相关的配置点。先看/etc/crontab没发现异常再看/etc/cron.d/在里面找到了一个文件名看起来像系统更新包残留的文件内容里有一段下载并执行远程脚本的逻辑。到这里持久化机制就已经定位了。接下来做全量检查把/var/spool/cron/下面所有用户的任务列表也翻了一遍又发现某个非 root 用户的任务列表里有一条定时执行临时目录脚本的记录。与此同时/var/log/cron里的执行记录也能对得上说明这个机制确实在按计划运行。4.3 清理步骤定位之后清理动作要按顺序做顺序错了很容易出现“清了又回来”的情况。先停掉当前的异常进程避免在清理过程中进程持续外连造成二次影响。然后删除计划任务配置里对应的条目这里要注意系统级和用户级的可疑任务都要清掉少一个都有可能卷土重来。接着把任务里引用的远端脚本从本地磁盘找出来确认文件内容之后一并删除。最后做复查再次遍历所有 crontab 配置点确认可疑条目已经不存在再用ss -antp看是否还有可疑外连最后检查临时目录下有没有新的可疑文件落盘。复查做完才算真正把这条持久化链路清干净。4.4 后续追踪清理完成后不只是恢复业务还要把漏洞入口堵上。复盘这次入侵路径入口很可能是一个暴露在公网上的服务存在未修补的漏洞攻击者利用漏洞进来之后设法获得了当前用户的权限然后利用计划任务做了持久化。所以后续动作有两块一是对受影响的应用做漏洞扫描和补丁更新二是收紧对外访问控制不必要开放的端口尽量不暴露在公网上。这两件事做完这台机器才算真正从“被入侵状态”回到“可信任状态”。5. 防御视角让计划任务不再成为后门温床5.1 把配置收口从防守角度讲最核心的动作是把计划任务的写入权限收口。系统级的 crontab 和/etc/cron.d/目录应该只允许 root 写入文件权限设置成 600 或者 644 但不允许普通用户修改。用户级的 spool 目录也一样普通用户只能操作自己的文件不能读写别人的。控制好这些写入入口之后还要做权限下放。有些团队习惯用 root 跑所有定时任务这是很不好的实践。任务本身如果只做日志清理或者数据同步完全可以用普通用户身份运行没必要给 root。降低任务运行权限等于降低了攻击者利用这个入口之后的危害范围。5.2 建立巡检基线有了权限控制还不够因为合法用户也可能被攻破真正的防线是持续巡检。我习惯的做法是把所有正常的计划任务梳理成一个白名单作为基线存档。基线内容至少包括任务文件的完整路径、文件名、执行内容、执行周期。日常巡检的时候把当前系统上的计划任务和基线对比新增的、改动的条目都会一目了然。配合文件监控工具来做效果更好一旦/etc/cron.d/、/var/spool/cron/这些目录发生文件新增或者修改立刻就能告警。5.3 日志与监控的配合单靠人工巡检很难覆盖所有时间点日志和监控的配合可以让防守效率提升很多。cron 的日志要保留合理的时间长度不能因为“占磁盘空间”就随便删。同时要做好外连监控特别是非标准端口的外连行为。把这些串起来看当 cron 执行了一条异常任务任务拉起一个进程进程发起一个外连这三个事件其实是一串连贯的动作。如果只有日志而没有连接监控你可能只会看到任务被多执行了几次却不知道它在往哪传数据。反过来也一样。只有把“配置、进程、网络”三个维度全部覆盖才能形成完整的检测闭环。6. 常见问题与经验速查6.1 做个检查清单下面这份清单适合日常安全巡检时快速对照也可以作为应急响应的排查指引。检查项具体操作判断标准系统级 crontab 文件查看/etc/crontab内容文件内只应有明确目的的管理任务cron.d 与周期目录列出/etc/cron.d/和周期目录下所有文件和内容文件来源应可追溯不应有临时脚本用户级任务遍历/var/spool/cron/目录及文件内容每个用户的任务应与该用户职责匹配cron 执行日志筛选/var/log/cron中高频及可疑任务任务名称与配置点对应不存在来源不明条目异常外连使用ss -antp审计对外连接远端口与目标地址应属于已知业务范围临时目录文件检查/tmp、/var/tmp、/dev/shm等目录不应存在需要周期执行的可疑脚本这个清单不是面面俱到但覆盖了最常见的计划任务持久化线索。实际执行的时候可以根据系统环境调整路径和命令。6.2 容易被忽视的三个细节细节一不要只看 crontab 命令本身。计划任务里可能只写了一行“看起来是系统命令”的内容实际这个命令是个包装过的二进制或者脚本真正的行为在文件里。所以排查时发现可疑任务必须顺着路径去确认被执行的到底是不是你以为的那个程序。细节二用户级任务和系统级任务要同等对待。很多排查者习惯先看/etc/crontab内容正常就觉得没事了。但用户级 spool 目录里的内容同样可以造成大量危害特别是非 root 用户的任务往往更隐蔽。细节三清理必须连同触发源一起处理。只删除 crontab 条目却不去管根本的入侵入口等于把门锁换了但钥匙还在别人手里。排查持久化永远要和漏洞修复同步进行否则同样的路径对方可以反复利用。6.3 踩坑之后的个人体会说实话crontab 这类持久化手法从技术上并不复杂但就是因为它不复杂反而更容易被忽略。很多系统管理员天天在用 crontab 做定时任务对自己的配置内容熟得不能再熟一旦多了一条任务反而不会立刻察觉。这种“熟悉带来的盲区”才是这类手法真正危险的地方。我自己的体会是安全运维不能只靠经验去找异常要给正常的配置打一个基线所有不在基线里的东西都当成异常来处理。经验当然重要但经验无法覆盖所有场景基线可以。花一点时间把现有服务器上的计划任务梳理清楚后面省下的排查时间远大于这点投入。还有一个建议巡检计划任务的频率不要设置得太低。最少每周一次有条件的最好每天一次而且要把检查结果留存下来。真出了问题这些历史记录能帮你快速判断问题是新出现的还是一直存在的节省大量回溯时间。