从后门到修复:Webmin CVE-2019-15107漏洞的完整时间线分析

从后门到修复:Webmin CVE-2019-15107漏洞的完整时间线分析

如果你在2019年关注过网络安全事件,一定对Webmin这个名字不陌生。这个看似普通的系统管理工具,因为一个编号为CVE-2019-15107的漏洞,在安全圈掀起了不小的波澜。但这个故事最吸引人的地方,远不止一个远程命令执行漏洞那么简单——它背后隐藏着一次精心策划的供应链攻击、一个被植入长达一年的后门,以及安全研究人员如何像侦探一样,从代码的蛛丝马迹中还原出整个攻击时间线。今天,我们就来深入聊聊这个漏洞背后的完整故事,看看从后门植入到最终修复,中间到底发生了什么。

1. 序幕:Webmin是什么,为什么它如此重要

在深入时间线之前,得先搞清楚Webmin到底是个什么东西。简单来说,Webmin是一个基于Web的Unix/Linux系统管理工具。想象一下,你管理着几十台服务器,每台都要通过SSH命令行去配置用户、设置防火墙、管理服务——这活儿既繁琐又容易出错。Webmin的出现,就是要把这些管理任务都搬到浏览器里,通过直观的图形界面来完成。

我第一次接触Webmin是在2015年,当时接手了一个小公司的服务器运维工作。那家公司没有专职的运维人员,几个开发人员轮流管理服务器,水平参差不齐。有人建议上Webmin,理由是“点几下鼠标就能搞定,不用记那么多命令”。确实,对于非专业运维人员来说,Webmin降低了门槛:配置Apache虚拟主机、管理用户账户、设置Cron任务,这些原本需要一定Linux基础的操作,在Webmin里变成了表单和按钮。

但便利性往往伴随着风险。Webmin默认监听10000端口,通过HTTPS提供服务,需要管理员账号密码登录。听起来挺安全,对吧?问题在于,很多中小企业的管理员为了方便,要么使用弱密码,要么干脆把Webmin暴露在公网上,还不做访问限制。更关键的是,Webmin本身是以root权限运行的——这意味着一旦Webmin被攻破,攻击者就拿到了服务器的最高权限。

根据Shodan等网络空间测绘引擎的数据,在漏洞曝光的2019年,全球有超过13万台Webmin服务器暴露在互联网上。这个数字可能还只是冰山一角,因为很多服务器部署在内网,外部扫描不到。这些服务器中,有企业用于管理内部基础设施的,有云服务商提供给客户的托管面板,甚至还有一些教育机构用来管理实验室机器。

Webmin的架构特点也值得注意。它完全用Perl编写,这在上世纪90年代末期项目启动时是个合理的选择,但到了2019年,Perl的流行度已经大不如前。整个系统由大量CGI脚本组成,每个管理模块对应一个或多个脚本。这种架构的优点是模块化程度高,容易扩展;缺点也很明显:每个CGI脚本都可能成为攻击面,而且Perl代码的安全审计相对PHP、Java等语言来说,专业的安全研究人员更少。

提示:如果你现在还在使用Webmin,强烈建议检查版本号。虽然CVE-2019-15107已经过去多年,但老版本可能还存在其他未公开的漏洞。最好的做法是升级到最新版本,或者考虑替代方案如Cockpit、Webmin的现代化分支Usermin等。

2. 事件起点:异常漏洞报告的浮现

时间来到2019年8月10日,这一天在Pentest博客上出现了一篇关于Webmin漏洞的详细分析。作者声称在Webmin的密码重置功能中发现了一个无需身份验证的远程命令执行漏洞,影响版本为1.920及之前。漏洞位于password_change.cgi文件中,攻击者可以通过向该页面发送特制的POST请求,在old参数中注入系统命令。

初看之下,这像是一个典型的输入验证漏洞。安全研究人员在审计代码时发现,password_change.cgi在处理用户修改密码请求时,会检查旧密码是否正确。如果旧密码错误,程序会调用pass_error函数显示错误信息。问题就出在这个函数调用上:

$enc eq $wuser->{'pass'} || &pass_error($text{'password_eold'}, qx/$in{'old'}/); 

第二行代码中,qx/$in{'old'}/是Perl中执行系统命令的语法,相当于反引号。正常情况下,这里应该只是把用户输入的旧密码作为错误信息的一部分显示出来。但代码编写者(或者说,修改者)犯了一个致命错误:他们直接把用户输入的$in{'old'}放进了qx//操作符中。这意味着如果攻击者在old参数中传入| id这样的值,Perl会先执行id命令,然后把输出作为错误信息的一部分。

但事情蹊跷的地方在于,这个漏洞的触发条件相当特殊。研究人员很快发现,要成功利用需要满足几个前提:

  1. Webmin必须开启“密码重置”功能(默认关闭)
  2. 使用的用户不能是系统用户(如root)
  3. 新旧密码需要符

Read more

Android端Whisper中文语音识别实战:从模型部署到性能优化

快速体验 在开始今天关于 Android端Whisper中文语音识别实战:从模型部署到性能优化 的探讨之前,我想先分享一个最近让我觉得很有意思的全栈技术挑战。 我们常说 AI 是未来,但作为开发者,如何将大模型(LLM)真正落地为一个低延迟、可交互的实时系统,而不仅仅是调个 API? 这里有一个非常硬核的动手实验:基于火山引擎豆包大模型,从零搭建一个实时语音通话应用。它不是简单的问答,而是需要你亲手打通 ASR(语音识别)→ LLM(大脑思考)→ TTS(语音合成)的完整 WebSocket 链路。对于想要掌握 AI 原生应用架构的同学来说,这是个绝佳的练手项目。 从0到1构建生产级别应用,脱离Demo,点击打开 从0打造个人豆包实时通话AI动手实验 在Android设备上实现高效的语音识别一直是个挑战,尤其是处理中文这种复杂的语言。最近我尝试将OpenAI的Whisper模型集成到Android应用中,过程中遇到了不少坑,也总结了一些优化经验,分享给大家。 移动端语音识别的特殊挑战 1. 算力限制:相比服务器,手机CPU和GPU性能有限,特别是低端设备。

告别复杂操作:灵感画廊极简AI绘画体验

告别复杂操作:灵感画廊极简AI绘画体验 "见微知著,凝光成影。将梦境的碎片,凝结为永恒的视觉诗篇。" 你是否曾经被复杂的AI绘画工具劝退?参数太多、界面太乱、学习成本太高...现在,这一切都将成为过去。灵感画廊(Atelier of Light and Shadow)基于Stable Diffusion XL 1.0打造,却彻底摒弃了工业化的复杂界面,为你提供一个如艺术沙龙般恬静的创作空间。 1. 为什么选择灵感画廊? 传统的AI绘画工具往往让人望而生畏。密密麻麻的参数滑块、晦涩难懂的技术术语、需要反复调试的复杂设置...这些都不是创作者想要的。 灵感画廊完全不同。它相信:真正的创作应该专注于灵感本身,而不是技术细节。 这里没有"提示词",只有"梦境描述";没有"反向词"

ClawdBot效果展示:语音消息→Whisper转写→英译日→Telegram推送全链路

ClawdBot效果展示:语音消息→Whisper转写→英译日→Telegram推送全链路 你有没有试过在 Telegram 群里听一段英语语音,想立刻知道它在说什么,又不想手动点开翻译软件、复制粘贴、再切回群聊?或者收到朋友发来的日语语音,却只能干瞪眼? ClawdBot 不是概念演示,也不是半成品 Demo。它是一套真正跑在你本地设备上的「端到端多模态翻译流水线」——从 Telegram 收到一条语音,到你在手机上看到准确的日语文字回复,全程无需上传云端、不依赖境外服务、不经过第三方服务器,耗时不到 3 秒。 这不是科幻设定,而是今天就能搭起来的真实体验。 1. 全链路效果实测:一条语音,三秒落地 我们不做抽象描述,直接看真实操作流。以下所有步骤均在一台普通笔记本(i5-1135G7 + 16GB 内存 + RTX3050)上完成,模型全部本地运行,无网络请求穿透防火墙。 1.1 场景还原:群聊中的一条英语语音

Matlab报错找不到编译器?5分钟搞定MinGW-w64 C/C++环境配置(附环境变量设置)

Matlab报错找不到编译器?5分钟搞定MinGW-w64 C/C++环境配置(附环境变量设置) 最近在尝试用Matlab调用一些C/C++写的算法库,或者想编译一个别人分享的.mex文件时,是不是经常在命令行里敲下 mex -setup 后,迎面而来的就是一个冰冷的报错窗口?"未找到支持的编译器或 SDK"——这句话对很多刚接触Matlab混合编程的朋友来说,简直像一盆冷水。别担心,这几乎是每个Matlab用户进阶路上的必经之坎。问题的核心,往往不在于Matlab本身,而在于你的电脑缺少一个它认可的“翻译官”:C/C++编译器。对于Windows用户,官方推荐且免费的解决方案就是MinGW-w64。这篇文章,就是为你准备的从报错到成功配置的完整路线图。我们不只告诉你步骤,更会解释每一步背后的逻辑,并附上那些容易踩坑的细节和验证方法,目标是让你一次配置,终身受益。 1. 理解问题根源:为什么Matlab需要单独的编译器? 在深入操作之前,花几分钟搞清楚“为什么”,能帮你避免未来很多“是什么”的困惑。Matlab本身是一个强大的解释型语言环境,