当前位置: 首页 > 技术干货 > B-Link X26路由器Web服务风险挖掘

B-Link X26路由器Web服务风险挖掘

发表于:2025-09-17 16:46 作者: 秋名山上的小柠 阅读数(17人)

0.前言

在对B-Link X26 V1.2.8 路由器固件进行安全审计时,发现其在处理特定输入的过程中存在命令注入溢出漏洞。

该漏洞的成因在于程序未对用户传入的数据进行严格的合法性校验,直接拼接进入系统命令,攻击者可以借此注入并执行任意代码。这种情况不仅可能导致设备运行异常,还可能在某些条件下使攻击者获得对路由器的完全控制。

通过验证与复测确认,该漏洞风险等级较高,利用门槛低,极易被远程攻击者滥用,对设备本身以及所处网络的安全性构成严重威胁。

目前,我已将漏洞细节、复现过程与修复建议整理成完整报告,并通过官方渠道提交给厂商及 CVE 分配机构。

该漏洞已被收录,编号为 CVE-2025-9580

1.漏洞概述

B-Link X26路由器 V1.2.8版本存在命令执行漏洞,触发该漏洞需要进行一次授权,当攻击者获取授权之后可以通过发送恶意的HTTP POST请求即可触发该漏洞。

2.漏洞详情

固件下载地址

官网下载完固件之后,使用binwalk进行解包。

这个固件解包出来后,比起之前其他我挖过其他消费级路由器也有很大不同。

首先它没有httpd文件,解包后习惯性地在 bin/sbin/ 目录中寻找 httpd 可执行文件,因为在大多数消费级或企业级路由器中,Web 管理界面往往依赖 httpd 作为核心服务。但在 B-Link X26 的固件中并没有找到 httpd,这使得常规思路无法直接套用。

接下来尝试在 Web 资源目录下寻找脚本文件,一般来说企业级路由器会包含大量 .php 脚本,比如 DCME-720 ,消费级路由器则可能依赖 .cgi 文件来处理。

后台逻辑,但是在 B-Link X26 中,.cgi 文件数量极少,仅发现了与上传相关的 upload.cgi。这与以往分析的 DCME、Wavlink 固件有明显不同:后者解包后能看到一整套配置、认证、状态查询相关的脚本,而在 X26 上,脚本层几乎不存在。

既然缺少传统的 httpd.cgi 文件也很少,说明该固件的 Web 服务逻辑并未像常见路由器那样拆分到大量脚本中,那么剩下的可能性,要么Web 服务被嵌入在某个非典型命名的二进制中,或者是路由器采用了轻量级嵌入式 Web 服务器。

带着这个假设,再次对 bin/ 目录进行排查,可以发现一个名为 goahead 的可执行文件。

通过字符串检索与反汇编分析,可以在 goahead 中发现大量 Web 服务相关的函数调用,比如 websGetVar、HTTP 请求处理逻辑,并且能定位到 system()popen() 等命令执行函数。

所以说B-Link X26 的 Web 管理界面核心逻辑全部集成在 goahead 内部,而不是依赖外部的 .cgi.php 文件。

回到正题,当请求路径为set_hidessid_cfg时候会进入sub_44F9F4函数的处理逻辑。

可以看到,这里从 HTTP 请求里取出参数 typeenablea1 通常是 webs_t 结构(goahead 的请求上下文),websGetVar 用来提取请求参数。

如果没取到,返回默认值 ""

然后又通过创建json对象的格式将参数打包成json对象传入到了bs_SetSSIDHide函数中,从名字可以看出来这是修改隐藏 SSID的配置的函数。

{
 "type":   "<用户输入的type参数>",
 "enable": "<用户输入的enable参数>"
}

那么这里就会有一些问题,typeenable完全是由用户输入的。

没有过滤,typeenable 原样地放进 JSON。

关键在于 bs_SetSSIDHide 的实现,如果说它内部调用了 system()/popen() 来修改无线配置,比如说执行 iwprivuci set 等命令,就可能引发命令注入。

但是如果只是直接操作配置文件/内存结构,则风险较小。

所以接着看 bs_SetSSIDHide 函数,但是这里有个问题,就是它是个外部函数,无法在gohead里面直接找到,这说明该函数并不在当前二进制中实现,而是来自外部库。

所以为了找到其具体的实现逻辑,首先检查了 goahead 的动态依赖库。

readelf -d goahead | grep NEEDED

该命令用于列出 goahead 这个程序运行时所必需的所有动态链接库,共享库文件。

查出了 goahead 运行时依赖的动态库,包括:libc.so.0,libnvrm.so.0,libshare.so.0之类。

既然 bs_SetSSIDHide 在 goahead 内部没定义,那么它必然来自这些依赖库之一。

根据经验,libshare.so.0 这个命名,share → 常常封装设备配置、WLAN、系统参数等接口,就可以合理怀疑这个函数实现藏在里面。

我们也可以验证一下猜测

nm -D libshare.so.0 | grep bs_SetSSIDHide

该命令用于检查名为 bs_SetSSIDHide 的函数是否存在于共享库 libshare.so.0 的动态符号表中,从而确认该函数是否可以被其他程序调用。

0002b7f4是函数 bs_SetSSIDHidelibshare.so.0 里的偏移地址,如果库被加载到内存,这个地址会加上库的基址,得到函数的真实运行时地址。

T表示该符号在 Text 段,也就是代码段中被定义,说明它是一个函数。字母 T 是大写的,这表示它是一个全局符号,意味着这个函数可以被链接到这个库的其他程序或库文件调用。如果是小写的 t,则表示它是一个内部函数,只能在库内部使用。

如果是 U,就表示 undefined,也就是未定义,只是引用。

bs_SetSSIDHide,就是符号名,也就是函数的名字,这说明 bs_SetSSIDHide 真正的实现就在 libshare.so.0 里。

这张图的输出证明了 bs_SetSSIDHide 在 libshare.so.0 中确实有定义(函数实现),地址偏移是 0x2b7f4,因此在 goahead 里调用的就是这个库函数。

所以按理来说我们应该去逆向分析libshare.so.0

但是由于其中 libshare.so.0 属于 共享对象名,其作用是给运行时动态链接器提供一个稳定的接口名称。

libshare-0.0.26.so 才是库的真实实现文件。通常情况下,libshare.so.0 会通过符号链接指向 libshare-0.0.26.so

所以直接处理 libshare-0.0.26.so就好,因为它包含了完整的符号信息与函数实现。

可以发现bs_SetSSIDHide将传入的两个json格式的对象进行了取值,并且接下来存在一个判断,对type取值为sethide2绕过这个if分支。

这里会发现对v20进行了命令执行,而v20是通过v7拼接而来的,而v7往上翻就是取到的值enable,也就是一开始传入的值。

那么这里就存在一个libc函数相关的命令执行。

3.漏洞验证

淘了一台真机,直接省事,懒得去仿真了(其实是仿真不起来....),真机才是硬道理!

然后去访问3.txt文件就会发现已经注入成功了。

本课程最终解释权归蚁景网安学院

本页面信息仅供参考,请扫码咨询客服了解本课程最新内容和活动

🎈网安学院推荐课程: 渗透测试工程师特训班 Web安全工程师特训班 Python网络安全实战班 应急响应安全工程师特训班
  CTF-Reverse实战技能特训班 CTF-WEB实战技能特训班 CTF-PWN实战技能特训班 CTF-MISC实战技能特训班   SRC赏金猎人大师班 HVV大师课