ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

服务器被植入挖矿木马?半小时应急清理与SSH安全加固实战指南

服务器被植入挖矿木马?半小时应急清理与SSH安全加固实战指南 我接到电话的时候对面语气已经有点慌了“我服务器CPU爆满网站打不开top一看有个进程叫kdevtmpfsi疯狂占CPU是不是被黑了”我让他先别重启远程连上去看了一眼心里大概有数了——典型的挖矿木马服务器被人SSH爆破进来种了挖矿程序当肉鸡。这种事儿我处理过不止一次快的话半小时能把木马清掉、后门堵上保住数据、保住这台机器。这事儿说到底是SSH安全没做到位。SSH作为Linux服务器日常管理的“大门”如果裸奔在公网上被爆破、被入侵只是时间问题。这篇文章我不讲空话直接把我这次“半小时救回云服务器”的完整过程整理成一套可复用的SSH安全加固指南从应急排查到漏洞修复再到日常防护全流程拆开揉碎给你看。如果你手头也有公网服务器强烈建议照着过一遍。1. 先搞清楚服务器是怎么被“搬走”当肉鸡的1.1 挖矿木马的典型入侵路径先说个扎心的事实绝大多数Linux服务器被入侵不是因为什么高级0day漏洞而是最基础的SSH弱口令和配置疏漏。攻击者没有针对你的业务系统做复杂的漏洞挖掘他们用的是全网扫描自动化爆破的“笨办法”。攻击过程大概是这样的攻击者用扫描工具扫网段找出所有暴露在公网、开放22端口的IP。用一份庞大的用户名密码字典里面包含root/admin/test这类常见账号以及123456、password这类弱密码对目标IP发起SSH暴力破解。一旦某个IP恰好用了弱口令攻击者就成功登录服务器获得shell权限。登录后攻击者会在极短时间内完成“下载挖矿木马→设置定时任务→清理日志→加入后门”这一套自动化流程把服务器变成矿机替他们挖门罗币XMR等匿名加密货币。整个过程快得惊人从爆破成功到木马跑起来往往不到一分钟。我第一次亲眼看到攻击日志的时候也吓了一跳——一台没加固的服务器一天能收到上万次SSH登录尝试。1.2 我朋友这台服务器犯的三个致命错误我上服务器查完发现朋友的这台机器几乎把所有该犯的错都犯了root账号直接允许密码登录root是Linux的超级管理员无论如何都不应该允许远程用密码登录。攻击者爆破root账号的成功率比爆破普通用户高得多。密码过于简单密码设成了类似Admin123这种“看起来复杂”但实际在字典里的组合。这种密码在爆破工具面前跟裸奔没区别。22端口直接暴露在公网没有修改默认端口也没有任何访问限制和暴力破解防护。等于把家门钥匙挂在门上还贴了张纸条写了“密码在下面”。这三个问题叠加在一起被入侵只是时间问题。朋友后来自己也承认买服务器的时候觉得“先跑起来再说”安全配置一拖再拖结果真出事了。1.3 被入侵后的“第一现场”长什么样我远程进去之后第一眼看到的情况是这样的top命令显示一个叫kdevtmpfsi的进程占用了接近1000%的CPU服务器是4核等于4个核全被占满。系统负载load average非常高网站响应极慢。/tmp目录下多了很多可疑文件比如kinsing、kdevtmpfsi这两个是同一家族挖矿木马的不同组件。crontab里被写入了一条定时任务每隔几分钟就从远程服务器下载木马并执行。known_hosts文件里出现了大量陌生的SSH指纹记录——这是攻击者用这台服务器作为跳板继续去扫别的机器留下的痕迹。如果你在服务器上看到类似现象不用怀疑机子已经被“搬走”了。这时候最忌讳的就是慌更忌讳直接重启——很多挖矿木马会在开机时自动重新加载你不清理干净就重启等于白忙活。正确做法是马上断网隔离然后按下面的步骤一步步排查。2. 应急响应半小时救回服务器的完整实操流程2.1 第一步断网隔离防止二次扩散我上服务器做的第一件事不是急着杀进程而是先断网。对于云服务器操作很简单登录云控制台在安全组规则里临时把出方向出站流量全部拒绝只保留我当前用来排查的IP放行或者干脆先关掉这台服务器的外网访问权限。为什么要先断网因为挖矿木马通常带有“更新”功能——它每隔几分钟就去C2服务器攻击者控制的服务端检查一次如果发现自己被清理了马上重新下载并再次执行。而且被入侵的服务器还可能成为跳板机对内网其他机器发起横向渗透。先断网隔离等于先把病毒“饿死”在本地控制住事态恶化。注意这一步非常重要但它有一个前提——你得确保自己能连上服务器执行排查命令。如果是云服务器建议用云控制台的“VNC登录”或者内网IP连接这样即使外网断掉也能操作。2.2 第二步揪出挖矿进程并彻底终止断网之后我重新连上服务器开始正式排查。先看进程top -c按下P键按CPU占用排序果然排名第一的还是kdevtmpfsiCPU占用接近1000%。接着我用ps命令查看这个进程的详细信息ps aux | grep -E kdevtmpfsi|kinsing输出结果让我注意到了几件事进程的可执行文件路径指向/tmp目录。同目录下还有kinsing进程它俩是同一个木马家族的“双人组”——kdevtmpfsi负责挖矿kinsing负责维持权限和后门。所有可疑进程都是以root身份运行的。这里要提一个关键技巧不要直接kill -9挖矿进程。很多木马会监控自己的主进程一旦发现子进程被杀死会立刻重新拉起。正确的做法是先找到木马的启动脚本和定时任务把“自愈”机制断掉。杀掉守护进程比如kinsing再杀挖矿进程本身。删掉木马文件清理所有相关配置。我当时先执行了# 找到木马相关的所有文件 ls -la /tmp/ find / -name kdevtmpfsi* -o -name kinsing* 2/dev/null然后逐一把找到的文件路径记录下来先不动文件因为在找到所有自启动入口之前删文件没有意义——它马上又会上传回来的。2.3 第三步排查并清理所有“自启动入口”挖矿木马要在系统里“扎根”必须设置自启动。我按下面的顺序把所有常见入口排查了一遍定时任务crontab这是最常被利用的入口。排查命令crontab -l # 查看当前用户的定时任务 cat /etc/crontab # 查看系统级定时任务 ls -la /etc/cron.d/ # 查看cron.d目录下的任务文件 ls -la /var/spool/cron/ # 查看各用户的cron任务结果在/var/spool/cron/root里发现了一条任务每隔5分钟从http://恶意域名/x.py下载脚本执行。我立即用crontab -r清掉了当前用户的任务然后手动编辑/etc/crontab删除了恶意条目。系统服务systemd木马还会注册成systemd服务来实现开机自启。排查systemctl list-unit-files | grep enabled ls -la /etc/systemd/system/ | grep -v \.wants find /etc/systemd/system/ -name *kdevtmpfsi* -o -name *kinsing*我在/etc/systemd/system/下找到了一个叫dbus.service的恶意服务文件——名字伪装成正常系统服务内容却是执行挖矿程序。杀掉进程后立刻禁用并删除systemctl stop dbus.service systemctl disable dbus.service rm -f /etc/systemd/system/dbus.service systemctl daemon-reload开机启动脚本检查/etc/rc.local、/etc/profile.d/、~/.bashrc、~/.profile这些文件cat /etc/rc.local ls -la /etc/profile.d/ grep -r wget\|curl /etc/profile.d/ ~/.bashrc ~/.profile 2/dev/null这轮检查果然有收获——/etc/rc.local里也被塞了一行启动命令指向/tmp/kinsing。我把整个rc.local文件清空恢复成默认状态。SSH authorized_keys这是攻击者给自己留的“后门钥匙”必须重点检查cat ~/.ssh/authorized_keys一看吓一跳文件里除了朋友自己的公钥还多了三四条攻击者的公钥。这意味着即使密码改了攻击者依然能用私钥免密登录。我直接把整个~/.ssh/目录权限收紧只保留一条确认安全的公钥其余全部删除。2.4 第四步查杀木马文件收尾清理确认所有自启动入口都清理干净后我这才回头处理木马文件本身pkill -9 -f kdevtmpfsi pkill -9 -f kinsing rm -f /tmp/kdevtmpfsi /tmp/kinsing rm -rf /tmp/.X11-unix # 部分木马家族的隐藏目录这里多说一句有些木马还会修改/etc/ld.so.preload通过预加载动态链接库的方式隐藏进程。如果你杀了进程之后top里明明看不到挖矿程序了但CPU占用依然异常十有八九是中了这种“进程隐藏”的马。检查方法cat /etc/ld.so.preload如果发现这个文件里出现了陌生的.so库路径马上清空这个文件然后重启服务器。这是很多运维踩过坑的地方光杀进程不查这个永远清理不干净。实操心得杀木马的正确顺序永远是“先断自启动入口定时任务、服务、启动脚本再杀进程、删文件”。反过来操作的话木马的守护进程会在几秒内把所有东西恢复原样你杀多少次都没用。2.5 第五步修改所有密码和密钥木马清理完之后服务器恢复到了“干净”状态。但这时候还不能松口气——攻击者可能已经掌握了服务器的账号密码不修改密码等于把门又敞开了。我做了三件事修改root密码passwd root用了一个高强度随机密码后面用密码管理器保存。修改所有用户密码逐个检查/etc/passwd把不认识的用户清理掉修改现有用户的密码。重新生成SSH主机密钥攻击者可能获取过旧的SSH主机私钥如果他用这个私钥冒充服务器你后续的SSH连接可能被中间人攻击。重新生成rm -rf /etc/ssh/ssh_host_* ssh-keygen -A systemctl restart sshd做完这些服务器的“急救”流程才算真正走完前后差不多半小时。3. 治本之策SSH安全加固的完整配置方案救回一台服务器只是治标。如果SSH配置还是原样用不了多久会被再次爆破入侵。接下来这套SSH安全加固方案我建议每台公网服务器都要做——不只是被入侵之后才想起来做新机器上线第一天就应该配好。3.1 修改SSH端口避开全网扫描把SSH默认的22端口改成其他端口是提高攻击门槛最直接、最有效的办法。全网扫描主要扫22端口的开放情况改了端口之后无差别扫描器基本找不到你攻击量会下降90%以上。修改方法vim /etc/ssh/sshd_config找到#Port 22这一行取消注释并改成Port 2222然后重启SSH服务生效systemctl restart sshd注意修改端口前一定要先在云控制台的安全组里放行新端口的入站流量再重启SSH服务否则你可能会把自己锁在外面只能去控制台用VNC连接救急。提示建议把新端口选在1024以上、不易被猜到的范围比如22022、22042这类既避开常规扫描的默认端口段又不容易被一些“常扫端口列表”命中。改完记得在云安全组里同时关闭22端口的公网入站。说句题外话很多人问我“改端口是不是会被认为有安全洁癖”但实际接触下来真正需要的不是面子是安全。3.2 用密钥登录替代密码登录密码登录最大的问题在于“可被暴力破解”。而SSH密钥登录使用的是非对称加密——客户端持私钥服务器存公钥没有私钥的人根本无法登录爆破字典再大也没用。配置步骤很简单第一步在本地生成密钥对如果还没有的话ssh-keygen -t ed25519 -C your_emailexample.com这里我推荐用ed25519算法密钥短、速度快、安全性高。现在新版本的OpenSSH都支持老系统如果内核较老可以用rsa但建议密钥长度至少4096位。第二步把公钥上传到服务器ssh-copy-id -p 2222 user服务器IP没有ssh-copy-id命令的手动追加也可以cat ~/.ssh/id_ed25519.pub | ssh -p 2222 user服务器IP mkdir -p ~/.ssh chmod 700 ~/.ssh cat ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys第三步修改sshd_config禁用密码登录PasswordAuthentication no ChallengeResponseAuthentication no UsePAM no然后重启SSH服务。这里的核心逻辑是只保留密钥登录密码登录彻底关掉从机制上杜绝暴力破解。3.3 直接禁止root远程登录root是攻击者最想拿到的账号——拿到root等于拿下整台服务器的控制权。所以root账号绝不能允许远程直接登录哪怕是密钥登录也不行。在sshd_config里加上PermitRootLogin no日常运维用一个普通用户登录如果需要root权限登录后执行su -或者sudo切换。这样即使普通用户密码泄露攻击者拿到的也只是普通权限破坏力大大降低。3.4 用Fail2ban做暴力破解自动封禁Fail2ban是一个入侵防御工具它会监控SSH登录日志如果某个IP连续多次认证失败就自动在防火墙层面封禁这个IP一段时间。安装并不复杂# Ubuntu/Debian apt install fail2ban -y # CentOS/RHEL yum install fail2ban -y配置加固编辑/etc/fail2ban/jail.local[sshd] enabled true port 2222 filter sshd logpath /var/log/auth.log maxretry 3 bantime 3600 findtime 600参数含义maxretry 3允许连续失败的次数超过即封禁。bantime 3600封禁时长单位是秒这里是一小时。findtime 600在10分钟内达到失败次数就触发封禁。启动并验证systemctl enable fail2ban systemctl start fail2ban fail2ban-client status sshd配置好之后我再也不会在日志里看到满屏的爆破尝试了。之前那些一天上万次的扫描现在连输密码的机会都没有直接被防火墙挡掉了。3.5 白名单访问控制最狠但也最稳的方案如果你的服务器IP是固定的比如办公环境、家里宽带有固定公网IP那更极致的方案是在防火墙层面对SSH端口做IP白名单限制。以云安全组为例入站规则里只放行你本机当前的IP访问SSH端口其他IP一律拒绝。这样任何扫描器连你的SSH端口都摸不到属于物理层面的“闭门谢客”。配合Fail2ban使用效果层次分明白名单放行真正的你任何IP都无法探测端口。即使白名单IP意外泄露Fail2ban还会兜底做爆破防护。实操心得如果是家用宽带IP是动态的用白名单会比较麻烦。你可以用DDNS动态域名解析配合云安全组的API自动更新白名单IP或者退一步用Fail2ban就够了。安全方案要适合自己的使用场景先跑起来再逐步加码。3.6 SSH配置参数逐项解读优化细节sshd_config里有很多默认配置项跟安全相关的参数我建议按下面这套来参数建议值原因说明Port非22端口避开全网无差别扫描PermitRootLoginno禁止root直接远程登录PasswordAuthenticationno禁用密码登录只保留密钥ChallengeResponseAuthenticationno关闭额外认证方式PubkeyAuthenticationyes开启公钥认证MaxAuthTries3限制单连接最大尝试次数LoginGraceTime30超时未登录自动断开ClientAliveInterval300心跳检测5分钟无响应断开ClientAliveCountMax2心跳超时2次即断开AllowUsersyourname白名单用户只允许指定用户登录Protocol2仅允许SSHv2协议这些参数都在/etc/ssh/sshd_config里修改改完记得sshd -t # 检查配置语法 systemctl reload sshd # 平滑重载配置不中断现有连接改动配置之前一定要先验证语法否则可能导致SSH服务启动失败把自己锁在门外。别问我怎么知道的好多运维都这么翻过车。3.7 双因子认证2FA进阶加固如果你对安全有更高的要求还可以给SSH加上TOTP双因子认证。即使密钥泄露没有手机上的动态验证码也登录不进去。实现方案用Google Authenticator即可# Ubuntu/Debian apt install libpam-google-authenticator -y # CentOS/RHEL yum install google-authenticator -y安装后执行google-authenticator生成密钥按提示绑定到手机上的身份验证器App。然后在/etc/pam.d/sshd文件顶部加上auth required pam_google_authenticator.so再修改/etc/ssh/sshd_configChallengeResponseAuthentication yes UsePAM yes AuthenticationMethods publickey,keyboard-interactive重启SSH服务后登录流程就变成了“私钥认证 手机动态码”双重验证安全性直接拉满。4. 后续加固系统层面的其他必要动作SSH加固完成不等于服务器就绝对安全了它只是堵住了最显眼的入口。一台服务器真正要扛住攻击还得把其他几个关键部位加固好。4.1 真伪对照入侵检测与日志监控SSH加固做得再到位也得有“监控”手段来确保万无一失。Linux系统的日志是排查入侵痕迹的第一手资料/var/log/auth.logUbuntu/Debian记录所有认证事件包括登录成功/失败。/var/log/secureCentOS/RHEL同上RedHat系系统的路径不同。/var/log/lastlog和last命令查看最近登录用户记录。journalctl -u ssh查看SSH服务的完整日志。我用过几款工具简单提一下供参考Lynis开源的安全审计工具可以一键扫描系统常见安全问题输出加固建议适合定期体检。ClamAVLinux上的杀毒软件虽然木马查杀率一般但对常见Webshell和挖矿木马还是有一定识别能力的。Rkhunter专门检测rootkit防御“进程隐藏”这类高级手法。这些工具的定位不是“装了就安全”而是“定期检查及时发现”。我个人的习惯是每月跑一次Lynis每周检查一次登录日志和系统负载形成习惯之后服务器出异常基本都能在早期发现。4.2 系统与软件更新修复已知漏洞攻击者除了爆破SSH还会利用系统组件存在的已知CVE漏洞进行攻击。比如一些老的Linux发行版内核漏洞、OpenSSL漏洞、Web服务组件漏洞都是入侵的突破口。更新策略很简单# Ubuntu/Debian apt update apt upgrade -y # CentOS/RHEL yum update -y生产服务器的更新建议先在测试环境验证再在正式环境执行。我见过有人在生产环境直接跑upgrade把服务搞挂的这种“怕漏洞不如怕自己”的教训实在不建议重蹈覆辙。4.3 最小化安装与服务暴露面服务器的攻击面来自“开着不需要的服务”。默认安装的Linux发行版会启动一堆用不到的服务比如邮件服务、打印服务、FTP服务等这些都是攻击者可以利用的入口。最小化加固原则用systemctl逐项检查正在监听网络端口的服务netstat -tlnp或ss -tlnp看哪些端口对外开放了。用不到的端口全部通过防火墙ufw/firewalld/云安全组关闭。不需要的服务直接停掉并禁用开机自启systemctl stop 服务名 systemctl disable 服务名我处理朋友这台服务器时发现上面居然还跑着一个非必需的FTP服务端口直接暴露在公网。这种“多余服务”是安全大忌——你永远不知道这些服务背后藏着多少已知漏洞。4.4 定期备份最后一道救命防线安全加固做再好也不能保证100%不被入侵。备份是你遇到最坏情况时的最后一道防线。备份策略三原则3-2-1原则至少3份数据副本存储在2种不同介质上其中1份存放在异地。自动化用crontab定时任务配合rsync或云服务商快照定期自动备份关键数据和配置。定期验证恢复备份不是“存了就行”定期做一次恢复演练确保备份真的能用。朋友的这台服务器幸好我之前帮他开过云快照虽然快照不是最新但至少重要数据没丢。否则真到了硬盘被加密勒索的那一步神仙也救不回来。5. 排查记录我的检查清单和恢复全过程最后把我这次“救火”的完整排查路径整理成清单你可以直接保存遇到类似问题按顺序走一遍。这套清单也是我处理其他服务器时的固定流程走了很多次效率很高。5.1 入侵排查自查清单步骤检查内容操作命令1当前系统负载和异常进程top -c按CPU排序观察2可疑网络连接ss -tnp看有没有连向陌生IP的主动连接3全部监听端口ss -tlnp确认对外暴露端口4定时任务crontab -l cat /etc/crontab ls /etc/cron.d/5系统服务systemctl list-unit-files | grep enabled6启动脚本cat /etc/rc.local ls /etc/profile.d/7SSH授权公钥cat ~/.ssh/authorized_keys8LD预加载隐藏进程cat /etc/ld.so.preload9异常用户cat /etc/passwd cat /etc/shadow10系统日志异常登录grep Accepted /var/log/auth.log | tail -505.2 木马清理实操流程按顺序执行云控制台安全组断网或隔离只保留排查通道。检查定时任务和服务禁用所有可疑的“自启动”入口。kill -9杀掉守护进程再杀木马主进程。删除木马文件及相关残留目录和脚本。清空/etc/ld.so.preload如果存在恶意库。检查并清理SSH的authorized_keys后门。修改所有账号密码重新生成SSH主机密钥。按第3节方案执行SSH安全加固。重启服务器再用升级后的密钥登录验证。持续观察24小时确认无异常再恢复业务。这整个流程熟练了大概半小时到一小时。第一次操作可能会手忙脚乱但还是那句话先断“自启动的根”再杀“跑着的进程”顺序不能乱。5.3 事后复盘安全加固是个“过程”不是“动作”把朋友的服务器救回来之后我给他做了个简单的安全体检又把这套SSH加固方案替他配置好。他对我说了一句让我印象很深的话“早知道这么麻烦当初买来就该弄。”其实不太麻烦。SSH加固这件事新服务器部署时顺手做一遍后面几乎零维护成本。而不做的话服务器一旦被入侵数据泄露、业务瘫痪、被勒索、被用来挖矿任何一项的代价都比加固本身高得多。从技术角度看服务器被入侵不是新鲜事被挖矿木马盯上更是每天都有人中招。从运维心态看“安全”永远是一个持续迭代的过程——没有绝对的安全只有相对更安全的配置。把基础的口子扎紧了攻击者自然会去找更软的柿子捏。这台服务器目前已经稳定运行了几个月朋友后来自己在后台看监控图表CPU负载长期保持在5%以下。他说这辈子都不会再用简单密码了我会心一笑——这大概就是“被社会毒打过之后再学安全”的真实感受吧。如果你手头的服务器也还没做SSH加固趁着这篇文章的热乎劲花半小时把自己从“潜在的肉鸡”名单里划掉。等你亲眼看到Fail2ban的封禁列表里躺着几百个扫描IP的时候你就知道这半小时花得有多值。
返回列表