Vulnerability Description

Vendor: Tenda

Product: AC10

Version: US_AC10V4.0si_V16.03.10.09_multi_TDE01

Type: Buffer Overflow

Firmware link: https://www.tendacn.com/material/show/104560

Vulnerability Details

The function R7WebsSecurityHandler copies HTTP parameters Password straight into fixed-size fields of the target structure v31 using strcpy() with no length checks. Supplying strings longer than these buffers over the /login/Auth endpoint lets a remote, unauthenticated attacker overflow the stack/heap, overwrite the saved return address, and execute arbitrary code as root or crash the service. In short, the function presents a classic buffer-overflow vulnerability exploitable via the Password parameter on all AC10 V4 firmware = 16.03.10.09.

int __fastcall R7WebsSecurityHandler(int a1, int a2, int a3, int a4, char *haystack)

char v31[128]; // [sp+15Ch] [+15Ch] BYREF

if ( strlen(v30) == 1 && v30[0] == 47 )
        {
          websRedirect(a1, "login.html");
          return 0;
        }
        if ( memcmp(v30, "/login/Auth", 0xBu) )
          goto LABEL_111;
        src = (char *)websGetVar(a1, "password", &unk_4EC8FC);
        Var = (char *)websGetVar(a1, "username", &unk_4EC8FC); // input
        if ( !Var || !src )
          goto LABEL_111;
        if ( strcmp(Var, g_User) || strcmp(src, &g_Pass) )
        {
          ...
          }
          if ( v22 < 0xFFFFFFFF )
          {
            memcpy(&g_loginErrorInfo[12 * v22], (const void *)(a1 + 48), 0x20u);
            g_loginErrorInfo[12 * (_DWORD)v22 + 11] = v25;
            ++g_loginErrorInfo[12 * (_DWORD)v22 + 8];
          }
          websWrite(a1, "HTTP/1.0 200 OK\\r\\n\\r\\n");
          websWrite(a1, "%s", "1");
          websDone(a1, 200);
          return 0;
        }
        SetValue("sys.userpass", &g_Pass);
        for ( m = 0; m < 3; ++m )
        {
          if ( !*((_BYTE *)&loginUserInfo + 68 * m) )
          {
            memcpy((char *)&loginUserInfo + 68 * m, (const void *)(a1 + 48), 0x28u);
            *((_DWORD *)&loginUserInfo + 17 * m + 10) = system_get_uptime();
            strcpy(v31, src); // buffer overflow
            goto LABEL_117;
          }
        }