TLS加密隧道也挡不住被植马

admin 2026-09-11 04:57:26 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 攻击者利用BGP劫持将Virtualizor更新流量导向恶意服务器,获取合法证书并分发恶意更新包,植入root后门。建议升级至3.2.9.9并运行安全分析器,检查IoC路径、轮换API密钥,确认失陷后需干净重装系统。 综合评分: 85 文章分类: 漏洞分析,应急响应,恶意软件,红队


TLS加密隧道也挡不住被植马

原创

suntiger suntiger

二进制空间安全

2026年9月10日 13:37 北京

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

将二进制空间安全设为”星标⭐️”

第一时间收到文章更新

安全事件背景

#

Virtualizor发布安全公告:同公司旗下Softaculous托管在德国云商Hetzner的地址段162.55.80.0/24遭遇BGP路由劫持,更新端点、客户区与账单站点的流量在约33小时内多次被转向攻击者控制的服务器。Virtualizor是安装在宿主机上的VPS虚拟化面板,用来管理KVM、OpenVZ等虚拟机;Softaculous负责一键安装WordPress等程序,Virtualizor的更新下载和客户登录也跑在这批服务器上;Hetzner是德国机房运营商。部分恰好在劫持窗口内检查更新的实例收到了恶意更新包,宿主机上留下root级持久化后门。

劫持原理

#

边界网关协议(BGP)是互联网上的路由交换协议。运营商对外发布某段IP该从哪些网络经过,相邻网络收到后通常直接采用,很少验证发布者是否真是那段地址的持有人。攻击者利用的选路规则是:同一个IP若同时落在两个网段里,路由器优先采用范围更小的那条路径。8月28日20:57 UTC起,自治系统62390未授权对外发布路由宣告,称网段162.55.80.0/24内的256个连续地址应经由其网络转发;Hetzner合法公布的则是把它包在内的更大网段162.55.0.0/16,约6.5万个地址。前者范围更小,在传播到的网络里,访问这256个地址的流量会被改到攻击者一侧。路径记录末尾仍挂着Hetzner的自治系统编号24940,从外部看源头还是Hetzner,不像整段IP换了主人,因此不易被察觉。

被劫持的网段上原本跑着Softaculous更新服务器、Virtualizor客户登录页和文件下载站。流量被改道后,这些本应发往官方机器的请求都会落到攻击者服务器上。免费证书机构Let’s Encrypt在签发证书前,会向域名对应的服务器发验证请求:要么让对方在网页固定路径上放一个约定文件,要么通过加密通道应答。验证流量同样被路由劫持,攻击者因此拿到了virtualizor.com、api.virtualizor.com、files.virtualizor.com等域名的合法网站证书。用户或更新程序连上去,证书检查会通过,浏览器不会报警。

网站证书在这里只证明一件事:你连上的那台机器持有该域名的合法凭证。它证明不了当前路由把你送到了不是官方真正控制的那台机器。Virtualizor更新客户端当时也不核对安装包有没有官方数字签名,只要加密连接建立成功、文件看起来像正常更新包,就会进入安装。2026年9月1日发布的3.2.9.9安全补丁加入了安全分析器,用来扫描已知后门文件,但截至2026年9月2日,强制校验更新包签名仍在后续开发中。

Virtualizor面板属于管理平面,负责创建虚拟机、分配IP、下发API指令、触发自动更新;宿主机操作系统和上面的客户虚拟机属于资源平面。这次攻击打的是管理平面到官方更新通道的信任链,一旦宿主机root失陷,资源平面上所有VM的磁盘、内存、网络都在同一信任边界内,租户数据面临被读取或篡改的风险。

攻击细节还原

首先,恶意更新包改写了三个Virtualizor核心文件:/usr/local/virtualizor/globals.php、/usr/local/virtualizor/_universal.php、/usr/local/virtualizor/zzvirtservice。注入代码会在后续被root用户的cron任务拉起。接下来,若系统没有Java17运行环境,脚本会先安装OpenJDK17,再从cdn.nerat.cc/installer/widdow.jar下载Java载荷到/tmp/widdow.jar,并写入/usr/lib/jvm/.cache/jre-runtime.dat,配套标记文件/usr/lib/jvm/.cache/.installed。

载荷执行后会做三件事:在/etc/systemd/system/java-jre-update.service注册systemd服务实现开机自启;往root账户authorized_keys写入攻击者SSH公钥(指纹SHA256:YQmy1hKF1h5cdJLxlZ5EScNoxe/UDWahjsWuQw2ERi8);创建名为proxyuser的本地账户供远程登录。Java后门还会回连connect.ne-rat.xyz,另有报告指向31.77.220.138:2025。额外标记文件/tmp/.vz_svc_done也在部分样本中出现。

恶意代码先写进合法面板文件,cron和systemd两层保证重启后仍存活,SSH密钥和隐藏账户留人工入口,Java载荷负责长期远控。globals.php等文件被改意味着面板业务逻辑本身已不可信,仅删Java文件不够,必须从已知干净备份恢复或重装系统。

修复方案

不同身份面对的暴露面不一样,处置优先级也不同。

跑Virtualizor的宿主机运维人员须对每台服务器逐项排查,官方未给出安全版本范围,不能因版本未知而跳过。第一步,登录面板升级到Virtualizor 3.2.9.9,在管理后台运行安全分析器。若分析器报告命中已知入侵指标,先联系Virtualizor支持保全证据,不要直接删除文件,以免破坏取证线索。第二步,人工核对以下路径和字符串,任意命中都应视为高度可疑:

/etc/systemd/system/java-jre-update.service/usr/lib/jvm/.cache/jre-runtime.dat/usr/lib/jvm/.cache/.installed/tmp/widdow.jar/tmp/.vz_svc_done/usr/local/virtualizor/globals.php、_universal.php、zzvirtservice内的cdn.nerat.cc或connect.ne-rat.xyz字样

第三步,轮换全部Virtualizor API密钥,删除陌生密钥,把API访问限制在可信源IP。第四步,审计root与各用户的authorized_keys、crontab、/etc/passwd里新增账户(尤其proxyuser),查最近SSH登录与异常出站连接,SSH只允许跳板机或固定办公网段。第五步,若确认root已被拿下,AlbaHost与多数安全从业者的共识是:干净重装是唯一长期可靠的恢复方式,面板文件恢复、密钥全换、VM快照也要重新评估信任。

下面这段Python脚本可在Linux宿主机上快速扫一遍公开IoC,不替代官方安全分析器,但适合批量初筛。运行环境:Python3.6+,无需额外依赖。

#!/usr/bin/env python3# -*- coding: utf-8 -*-"""Virtualizor BGP事件 IoC 快速初筛(2026-09)"""import hashlibimport osimport sys
IOC_PATHS = [    "/etc/systemd/system/java-jre-update.service",    "/usr/lib/jvm/.cache/jre-runtime.dat",    "/usr/lib/jvm/.cache/.installed",    "/tmp/widdow.jar",    "/tmp/.vz_svc_done",]IOC_STRINGS = [    "cdn.nerat.cc",    "connect.ne-rat.xyz",    "jre-runtime.dat",    "widdow.jar",]PHP_TARGETS = [    "/usr/local/virtualizor/globals.php",    "/usr/local/virtualizor/_universal.php",    "/usr/local/virtualizor/zzvirtservice",]PAYLOAD_SHA256 = "b81a4e1fab9fc4e404d57224fe71e2c143aa93942bd46998789bdc944a7870c7"
def sha256_file(path):    h = hashlib.sha256()    with open(path, "rb") as f:        for chunk in iter(lambda: f.read(65536), b""):            h.update(chunk)    return h.hexdigest()
def main():    hits = []    for p in IOC_PATHS:        if os.path.exists(p):            hits.append(f"[文件存在] {p}")            if p.endswith("jre-runtime.dat"):                try:                    if sha256_file(p) == PAYLOAD_SHA256:                        hits.append(f"[哈希匹配] {p}")                except OSError as e:                    hits.append(f"[读取失败] {p}: {e}")    for p in PHP_TARGETS:        if not os.path.isfile(p):            continue        try:            data = open(p, encoding="utf-8", errors="ignore").read()        except OSError:            continue        for s in IOC_STRINGS:            if s in data:                hits.append(f"[字符串命中] {p} -> {s}")    if hits:        print("发现可疑指标:")        print("\n".join(hits))        sys.exit(2)    print("未发现已知IoC路径/字符串,仍建议运行官方安全分析器并查SSH/cron。")    sys.exit(0)
if __name__ == "__main__":    main()

保存为check_virtualizor_ioc.py后执行:python3 check_virtualizor_ioc.py。退出码2表示有命中。

在8月28至30日窗口内登录过Virtualizor/Softaculous客户区或提交过支付信息的用户,应立刻修改客户区密码,并在其他网站停用相同密码。若当时输入过银行卡信息,对照账单看是否有异常扣款。使用Client Center API的,在官网重新生成密钥并同步到自有自动化脚本。

同一生态里跑Webuzo、Softaculous自动安装器、Backuply、SitePad的运维,目前官方未确认这些产品有恶意包,但如果在劫持窗口内做过更新检查,建议对照访问日志、面板版本和上述网络侧异常,保持关注后续公告。

IOC

C2 CDN:cdn.nerat.cc

C2: connect.ne-rat.xyz

download URL: cdn.nerat.cc/installer/widdow.jar

SSH登录来源:193.32.127.248

C2 IP地址与端口:31.77.220.138:2025

#

(全文完)


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:二进制空间安全 suntiger suntiger《TLS加密隧道也挡不住被植马》

评论:0   参与:  0