
接到电话那天我记得很清楚业务部门反映某台数据库服务器负载异常飙升CPU长期在90%以上访问量没涨的情况下慢查询报文堆了一堆。上去一看MySQL进程占了大部分CPU但业务方说没有跑任何批量任务。直觉告诉我这不是容量问题是有人进来了。后面排查下来确实是Linux层被植入了挖矿进程MySQL侧也被留了后门账号和恶意UDF一套典型的入侵组合拳。这类“Linux入侵排查日志分析MySQL应急响应”的活实操起来其实有固定套路。很多人一上来就翻日志翻了一晚上什么都没看出来原因是思路没理清楚。这篇文章就把我从接到告警到最终清理加固的全过程拆开讲包含系统层排查、日志分析、MySQL专项排查三大部分所有命令都是实际能用并且验证过的。如果你也遇到类似的服务器异常照着这个顺序走一遍大概率能把问题定位出来。1. 应急响应核心思路先把“止损”和“溯源”分开很多新手第一次参与应急响应上来就想抓住攻击者、还原完整攻击链结果在日志里越陷越深服务器上的恶意进程还在跑数据还在被偷。这是大忌。应急响应的第一原则不是抓人而是止损。先把入侵影响控制住再考虑溯源分析。1.1 一场典型入侵的完整链路先建立一个通用模型。大多数针对LinuxMySQL的入侵路径是相似的外部暴露面被打穿最常见的是SSH弱口令暴力破解、Redis未授权访问、Web应用漏洞RCE。攻击者获得一个普通权限的shell然后通过内核漏洞、sudo提权、SUID文件、或者MySQL UDF提权等方式拿到root权限。落地持久化手段包括写SSH公钥、添加系统账号、修改crontab、写自启动脚本、植入内核模块、MySQL层面写UDF或触发器。进行横向渗透或直接牟利常见动作是下载挖矿木马、窃取数据库数据、加密勒索。应急响应的排查过程其实就是把上面的链路反过来走一遍先发现恶意进程和连接然后找到启动方式再找到上传的文件和入侵入口。1.2 排查黄金时间与最小取证原则从发现入侵到完成隔离这个窗口期越短越好。攻击者在服务器上待得越久留下的后门和窃取的数据就越多。接到告警后我建议按以下优先级操作第一优先级隔离网络通过防火墙限制受感染服务器的出站连接防止数据外传和横向扩散。第二优先级保留证据操作前先备份日志、进程列表、网络连接、内存信息这些是后续溯源的基础。第三优先级排查和清理按照系统层到应用层的顺序逐项排查。第四优先级恢复和加固修补漏洞、改密、收敛权限。取证有个“最小操作”原则不要在目标机器上装太多新工具因为攻击者可能替换过系统命令你用被替换过的ps、netstat去查结果可能完全被欺骗。最好用静态编译的工具或者直接基于/proc文件系统手查。提示如果条件允许先对受害服务器的内存做一份镜像再用volatility分析很多只存在于内存中的无文件攻击只能通过内存取证发现。不过大部分中小企业没这个条件所以本文以常规日志和系统排查为主。1.3 应急排查准备清单动手之前先把下面这些东西准备好能省很多事准备项用途说明独立终端记录本记录关键输出所有命令输出保留时间戳方便后续做时间线外置存储或远端日志服务器备份日志确认日志没有被攻击者清空前先整体打包保存一份静态排查工具包绕过被替换命令备一份busybox或者静态编译的ps、netstat、lsof对端IP威胁情报查询渠道判断连接来源用于确认对外连接的IP是否为已知恶意IP数据库账号清单排查后门账号提前拿到业务方提供的合法账号列表才能区分正常与恶意准备工作不用超过十分钟但能帮你少走大量弯路。2. Linux系统层入侵排查账号、进程、启动项、文件四个维度进入系统后的排查要按维度逐层过而不是东敲一下西看一眼。我习惯按“账号-进程-网络-启动项-文件”的顺序来每个维度都有几条固定的命令组合。2.1 账号与登录痕迹排查第一个该看的地方攻击者拿到权限后第一件事通常是留一个后门账号。检查账号相关文件能最快发现异常。重点检查以下文件# 查看所有用户和登录shell cat /etc/passwd # 查看密码文件注意哪些账号有登录权限同时密码字段异常 cat /etc/shadow # 查看sudo权限 cat /etc/sudoers grep -r sudo /etc/sudoers.d/这里要重点看三种情况新增的账号尤其是UID为0的非root账号这种账号拥有root权限但用户名不是root。登录shell为/bin/bash但不是系统用户的账号比如莫名多了一个名为mysql、nginx或test的用户而且有shell。/etc/passwd中密码位是密文而非x的账号这意味着该账号可能被写入了一个已知密码的哈希。检查登录痕迹的命令# 查看最近登录记录 lastlog last -a # 查看当前登录用户 who w # 查看登录历史审查wtmp、btmp last -f /var/log/wtmp lastb -f /var/log/btmplastlog会显示每个账号最近一次登录时间如果一个很久不用的账号突然有了新登录记录那基本可以确认被利用了。lastb查看的是失败登录记录可以判断是否有过针对性的暴力破解尝试。# 检查SSH认证日志中的成功登录记录 grep Accepted /var/log/auth.log grep Accepted /var/log/secure如果服务器被清了日志还可以检查~/.bash_history攻击者往往会忽略清理root的历史命令。看历史命令里是否有下载外部的脚本、写入crontab、修改用户等敏感操作。# 查看root历史命令 cat /root/.bash_history # 查看所有用户的历史命令 find /home -name .bash_history -exec cat {} \;历史命令是一个非常关键的溯源数据源。我遇到过的很多案例攻击者忘了清历史命令完整操作流程直接暴露在眼前省了大量排查时间。2.2 恶意进程与网络连接排查找到正在运行的后台木马进程排查的核心目标是找出CPU、内存占用异常的可疑进程以及建立可疑外连的进程。# 查看进程列表按CPU和内存排序 ps aux --sort-%cpu | head -20 top -c htop -c挖矿木马的特征很明显进程名通常是随机字符串CPU占用接近100%而且进程以root权限运行。# 查看与外部地址建立的连接 ss -antp netstat -antlp # 查看监听端口 netstat -nlp ss -lnp重点关注ESTABLISHED状态的连接中是否有连接明文矿池地址或高危端口例如22以外的SSH、3306、6379等以及常见的C2端口。监听端口里是否有不在业务范围内的端口。这里有个实战小技巧用lsof -p PID查看可疑进程打开的fd以及ls -l /proc/PID/exe和/proc/PID/cwd查看进程的真实二进制路径。很多攻击者会修改进程名伪装成kworker、ksoftirqd之类的内核线程名但/proc里的信息很难伪装完整。例如进程名看着是[kworker]但/proc/PID/exe却指向/tmp/x这种基本就是木马。# 查看进程的真实二进制路径 ls -l /proc/进程PID/exe cat /proc/进程PID/cmdline后面排查工作把进程杀掉之前一定要先把进程名、PID、父进程PID、启动时间、二进制路径记录下来。父进程信息可以帮助定位进程是被哪个程序拉起来的。2.3 启动项与定时任务排查识别持久化后门进程清掉了还会再起来关键原因是启动项没清干净。攻击者常用的持久化手段就体现在下面这些检查项里。# 查看crontab任务 crontab -l cat /etc/crontab ls -la /etc/cron.d/ cat /etc/cron.d/* ls -la /var/spool/cron/ cat /var/spool/cron/* atq攻击者写入的crontab任务有两个特点时间间隔很短比如每分钟执行一次命令内容常见为从远程下载脚本再执行。# 查看系统启动时执行的脚本 cat /etc/rc.local ls -la /etc/init.d/ systemctl list-unit-files --typeservice # 查看所有systemd服务排查新添加的服务 systemctl list-unit-files | grep enabled systemctl cat 服务名# 排查环境变量文件常见后门位置 cat /etc/profile cat /etc/bash.bashrc cat /root/.bashrc cat /root/.profile cat /root/.bash_profile攻击者可以把后门逻辑写到shell启动文件里用户每次登录时自动执行。特别是如果发现/root/.bashrc里多了一行/tmp/.cache之类的执行语句那基本就是持久化后门。2.4 可疑文件与后门排查定位webshell和落地脚本这一轮排查的目标是找到攻击者上传的恶意文件。# 查找最近一天内新增或修改的文件 find / -mtime -1 -type f -name *.php 2/dev/null find /tmp -type f -mtime -1 2/dev/null find /var/tmp -type f -mtime -1 2/dev/null # 查找特殊扩展名的文件重点是常见储备目录 find /tmp /var/tmp /dev/shm /tmp -type f \( -name *.sh -o -name *.py -o -name *.pl -o -name *.so -o -name *.elf \) 2/dev/null攻击者喜欢把文件放/tmp、/var/tmp、/dev/shm这几个目录因为这些目录默认任何人都能写。/dev/shm内存盘上的文件重启后会自动消失如果这里出现脚本或二进制基本可以确认是入侵样本。# 查找SUID文件重点看近期修改 find / -perm -4000 -type f 2/dev/null ls -al /usr/bin/passwd /usr/bin/su 2/dev/nullSUID文件是提权后门的常见形式。如果发现一个近期出现的、拥有SUID权限、且不是系统常规SUID列表中的可执行文件比如/tmp下有个SUID的find很可能是攻击者复制的提权工具后门。如果服务器上运行的是Web服务还需要做webshell检测。Web目录下可疑PHP、JSP、ASP文件特征通常是包含eval、assert、system、base64_decode、gzuncompress等函数。# 在web目录中查找常见webshell特征 grep -r eval(\$_POST /var/www/html/ grep -r base64_decode /var/www/html/ grep -r system(\$_GET /var/www/html/一个经验判断标准web目录中出现非业务方上传的x.php、shell.php、1.php这类文件名或者在图片文件末尾发现PHP代码的基本是webshell。3. 日志分析实战从海量日志里还原入侵时间线日志分析是应急响应的灵魂也是大多数新人觉得最无从下手的地方。海量日志堆在那里不知道看哪行。我这里分享一套比较实用的日志分析路径能快速定位攻击行为和时间线。3.1 认证日志分析破解SSH暴力破解与登录后门SSH是Linux服务器最常被攻击的入口。认证日志通常位于/var/log/auth.logDebian系或/var/log/secureCentOS系。# 查看所有认证失败记录 grep Failed password /var/log/secure | wc -l # 查看失败次数最多的IP grep Failed password /var/log/secure | awk {print $(NF-3)} | sort | uniq -c | sort -nr | head -20 # 查看认证成功的时间线 grep Accepted /var/log/secure | tail -50如果某个IP失败几百上千次那是暴力破解。但真正危险的不是暴力破解而是成功后登录的IP。上面grep Accepted的结果要跟业务方的合法运维IP列表比对凡是列表中不存在的IP都需要标记为可疑登录。另一个容易忽略的点是SSH的异常配置。检查/etc/ssh/sshd_config是否被修改过比如端口被改了、PermitRootLogin被开启了、公钥认证里被添加了恶意公钥。# 查看authorized_keys文件重点检查新增的公钥 cat /root/.ssh/authorized_keys find /home -name authorized_keys -exec cat {} \;攻击者最典型的操作是把公钥追加到某个用户的authorized_keys文件里之后直接用私钥登录不需要密码。我在一次排查中就发现某个用户多了一行明显不属于该用户的公钥注释内容是一串随机字符串时间戳也和其他文件不一致。3.2 系统日志与历史命令还原攻击者在服务器上的操作系统日志方面需要关注/var/log/messages或/var/log/syslog# 查看系统日志重点看异常的服务启动和崩溃信息 tail -200 /var/log/messages # 查看被错误记录的系统事件 journalctl -xe --no-pager | tail -100对于溯源来说历史命令比系统日志更有价值。~/.bash_history往往能还原攻击者的完整操作链。为了更精确地定位攻击者在什么时间执行过什么命令还可以检查/var/log/audit/audit.log如果系统装了auditd# 查看root用户的命令审计 ausearch -ua root -ts today没有auditd的情况下bash_history的时间戳拿不到那就结合文件时间戳来推断。比对恶意文件的stat信息和日志时间能大致还原攻击者在服务器上的行为顺序。3.3 日志时间线用一张表定位攻击窗口日志分析到最后要形成一条清晰的时间线。我的做法是把所有关键事件写进一个表格时间事件日志来源涉及IP/进程备注03:15:22SSH暴力破解成功/var/log/secure114.x.x.x来源IP未在白名单03:16:01root执行wget下载脚本/root/.bash_history—下载来源未知域名03:17:45crontab新增定时任务/var/spool/cron/root—执行周期1分钟03:20:113306端口出现异常连接ss -antp内网IP段疑似数据库被访问时间线一旦形成排查和汇报都很方便后续做应急报告时这个时间线就是核心素材。4. MySQL数据库专项应急排查后门账号、恶意UDF和日志标记Linux系统层排查完之后如果这台服务器是数据库服务器还要做数据库本身的专项排查。MySQL应急响应和常规系统应急响应的侧重点很不一样除了系统层的后门数据库自身有一条独立的入侵路径。4.1 MySQL入侵的常见路径从弱口令到UDF提权了解排查目标之前先熟悉攻击者是怎么打MySQL的弱口令直接连接常见root空密码、root/123456、test/123456这类组合。通过Web应用的SQL注入或文件读取漏洞把MySQL数据拖走或者写入webshell。通过MySQL的SELECT ... INTO OUTFILE写文件到web目录实现一个webshell。通过MySQL的UDF机制上传恶意.so文件注册成自定义函数然后用这个函数执行系统命令完成提权。通过MySQL Event调度器或者触发器在数据库内部维持持久化。看到这里你应该明白了MySQL应急响应不只是看数据库日志那么简单它和系统层的文件排查是联动的。尤其是UDF提权恶意.so文件会落到MySQL插件目录这就是一个典型的“系统层数据库层”结合点。4.2 MySQL日志层排查从错误日志到binlog逐层过MySQL日志主要分四类每一类的排查侧重点都不同。首先看错误日志-- 在MySQL中查看当前日志配置 SHOW VARIABLES LIKE log_error; SHOW VARIABLES LIKE general_log%; SHOW VARIABLES LIKE slow_query_log%;# 在系统层查看错误日志文件内容 tail -200 /var/log/mysql/error.log错误日志主要看有没有异常重启记录、插件加载失败记录、以及明显的恶意连接信息。通用查询日志是排查SQL操作的重武器如果服务器开了general_log所有查询语句都会被记录。这日志平时不要开但排查时如果没开就得想办法从其他日志找线索。# 查看general log内容找可疑SQL grep -i select.*into outfile /var/log/mysql/mysql.log grep -i load_file /var/log/mysql/mysql.log grep -i sleep /var/log/mysql/mysql.log grep -i benchmark /var/log/mysql/mysql.log这几个关键字对应了MySQL入侵里最常见的动作写webshell、读本地文件、DoS探测、延时盲注。慢查询日志在入侵排查中也很有用攻击者做SQL注入盲注时会用benchmark或sleep函数人为制造延时这种查询通常会被记录到慢查询日志。grep -i benchmark /var/log/mysql/slow.log grep -i sleep /var/log/mysql/slow.logbinlog是最后一道防线也是最全的日志binlog是二进制格式需要用mysqlbinlog工具解析# 查看binlog文件列表 mysql -e SHOW BINARY LOGS; # 解析指定binlog文件中的SQL mysqlbinlog --base64-outputDECODE-ROWS -v mysql-bin.000012解析后重点找INSERT、UPDATE、DROP、DELETE操作尤其是对mysql.user表和mysql.func表的修改。攻击者添加后门账号或者删除日志时会留下binlog记录。临时开启通用日志来做实时监控也是可行方案SET GLOBAL general_log ON; SET GLOBAL general_log_file /tmp/mysql_audit.log;排查期可以临时开一段时间把可疑连接的行为记录下来。这个操作要记得排查结束后关闭因为通用日志写入开销很大排查期间开着可以开太久会影响性能。4.3 MySQL账号权限与函数排查发现后门账号和恶意UDF日志是侧面证据直接查数据库的账号和函数则是最直接的方法。-- 查看所有用户和host SELECT user, host, authentication_string FROM mysql.user; -- 查看用户权限 SHOW GRANTS FOR 用户名主机; SELECT * FROM mysql.user WHERE User 可疑用户\G;排查账号有三个原则已知合法账号列表之外的全部标记可疑。host字段为%而业务不需要远程登录的标记可疑。权限包含SUPER或ALL PRIVILEGES的非管理员账号标记可疑。MySQL后门账号的常见命名包括mysql、root2、backup、test、admin等。有些攻击者会直接把rootlocalhost的密码哈希替换掉改成自己的密码这种排查时需要关注密码哈希最近是否被修改过。再看UDF提权后门-- 查看系统自定义函数 SELECT * FROM mysql.func;正常系统里mysql.func表通常是空的。如果里面有函数且函数对应的dl字段指向一个.so文件基本可以判定是UDF后门。# 查看MySQL插件目录 mysql -e SHOW VARIABLES LIKE plugin_dir; # 列出插件目录中的文件 ls -la 插件路径恶意UDF的.so文件通常有随机文件名比如wqlf.so、udf.so这类。攻击者上传后使用CREATE FUNCTION sys_exec RETURNS STRING SONAME udf.so这类语句注册一个执行系统命令的函数然后通过select sys_exec(命令)来执行系统命令。清除UDF后门的操作-- 删除恶意函数 DROP FUNCTION 函数名;然后删除插件目录下的恶意.so文件同时检查/tmp、/var/tmp是否有同源的二进制文件。4.4 MySQL恶意连接与数据窃取排查数据库层的另一个排查重点是连接来源和连接行为。# 查看当前MySQL连接数和来源 mysql -e SHOW PROCESSLIST; mysql -e SELECT id, user, host, db, command, time, info FROM information_schema.processlist;SHOW PROCESSLIST是排查MySQL异常时最常用的命令之一。重点看连接host是否有陌生IP尤其是非业务网段的IP。command为Query且info里包含SELECT * FROM mysql.user、SELECT * FROM mysql.func这类系统表查询的很可能是攻击者在查看账号与后门。time特别大且state异常的会话要留意是否有大文件导出操作。如果怀疑数据已经被窃取还可以检查binlog里是否有大批量SELECT语句或者通过通用日志观察是否有数据导出行为。对于已经外泄的数据立即修改所有数据库账号密码、限制host授权然后通过防火墙封禁对方IP。4.5 MySQL入侵后的清理与加固清理的具体操作按下面几点走删除恶意用户、函数、触发器、事件。修改所有应用账号的密码通知业务方同步修改。清理web目录下的webshell文件。检查是否有my.cnf被修改比如secure_file_priv权限、skip_grant_tables等危险配置。确认MySQL版本如果有已知漏洞则升级。加固建议方面重点几件事# my.cnf建议加固项 [mysqld] # 禁止导入本地文件 local-infile0 # 限制导入导出目录 secure_file_privNULL # 不跳过授权表 # skip-grant-tables 删除此项 bind-address127.0.0.1-- 给应用账号最小权限不要随便给SUPER GRANT SELECT, INSERT, UPDATE, DELETE ON 数据库.* TO x内网IP;数据库账号权限收敛是个长期工程但至少先做到权限最小化。5. 常见问题与排查技巧实录那些容易踩坑的细节5.1 常见问题速查表现象可能原因排查方向CPU飙高但业务无增长挖矿木马top -c定位高CPU进程检查/proc/PID/exe清理crontab和启动项登录记录里有陌生IP成功登录SSH被爆破成功或公钥后门检查authorized_keys修改密码封禁来源IP查看bash_history数据库多了一个不确定的账号MySQL后门账号mysql.user表对比合法清单清理多余账号修改密码mysql.func表出现记录UDF提权后门删除恶意函数和.so文件确认插件目录无残留binlog里出现DROP TABLE数据库被恶意破坏用binlog配合mysqlbinlog恢复排查删除操作的会话和来源定时任务里出现下载脚本持久化后门清理crontab检查脚本内容和下载来源自查启动项文件权限异常出现SUID提权后门find / -perm -4000清理可疑SUID文件历史命令被清空攻击者清理痕迹检查wtmp、btmp、auditd等其余来源5.2 应急响应中容易忽略的“坑”第一个坑只清进程不清理启动项。挖矿木马往往同时存在进程和定时任务两个形态只杀掉进程隔几分钟又会出现因为父进程或crontab会在下一轮重新拉起它。正确做法是先删除定时任务、再杀进程、最后清理文件顺序反了等于白干。第二个坑用被替换过的命令做排查。攻击者可能在系统上放了替换过的ps、netstat、ls专门用来隐藏恶意进程和文件。如果你用了这些命令看到的只是攻击者想让你看到的假象。排查时优先用busybox这类静态编译工具少依赖系统自带的命令。第三个坑不做网络隔离就让服务器继续对外服务。发现入侵后应该第一时间在防火墙或安全组上限制受感染服务器的出站流量尤其是对外的TCP连接。很多攻击者的后续动作是在后台持续上传数据或进行横向渗透把出站流量切掉能极大限制损失。第四个坑疏忽了数据库层面的后门。很多应急响应做完系统层排查就结束了结果数据库账号和UDF后门还留在那里。攻击者随时可以通过后门账号重新登录前脚清理完后脚又被打回来。MySQL侧一定要单独做一遍账号、函数、事件、触发器检查。5.3 一个可以复用的排查脚本思路排查熟练之后可以把自己的固定命令整理成脚本每次应急响应直接跑一遍效率会高很多。脚本核心就做几件事记录当前时间、备份敏感日志、收集用户和登录信息、收集进程和网络连接、输出crontab、扫描可疑文件。脚本本身不复杂真正的价值在于每次用的都是同一套命令输出格式固定对比起来方便。我自己实际用下来的体会是应急响应这件事七分靠排查习惯三分靠工具。能跑完上面的流程、形成完整时间线、把后门清干净、把漏洞堵上一次应急响应就算是成功了。剩下更重要的是复盘这次是怎么进来的、下次怎么防住。好的应急响应不只是收拾烂摊子更是帮业务把地基打牢。