CVE-2022-38451
A directory traversal vulnerability exists in the httpd update.cgi functionality of FreshTomato 2022.5. A specially crafted HTTP request can lead to arbitrary file read. An attacker can send an HTTP request to trigger this vulnerability.
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
FreshTomato 2022.5
Siretta QUARTZ-GOLD G5.0.1.5-210720-141020
AdvancedTomato commit 67273b0
FreshTomato - https://www.freshtomato.org/ QUARTZ-GOLD - https://www.siretta.com/products/industrial-routers/4g-lte-router/gigabit-ethernet-small-footprint-lte-router-eu/
6.8 - CVSS:3.0/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:N/A:N
CWE-22 - Improper Limitation of a Pathname to a Restricted Directory (‘Path Traversal’)
FreshTomato is an open source firmware based on linux. The firmware offers several features for Broadcom-based routers.
The FreshTomato’s httpd component offers a simple template language to call an API during the loading of the HTML page. This process is performed through asp api
. The asp api
normally is not directly callable, but a FreshTomato’s API called update.cgi
will allow it.
Following is one of the functions responsible for performing the update.cgi
API:
static void wo_update(char *url)
{
const aspapi_t *api;
const char *name;
int argc;
char *argv[16];
char s[32];
if ((name = webcgi_get("exec")) != NULL) {
for (api = aspapi; api->name; ++api) {
if (strcmp(api->name, name) == 0) {
for (argc = 0; argc < 16; ++argc) {
snprintf(s, sizeof(s), "arg%d", argc);
if ((argv[argc] = (char *)webcgi_get(s)) == NULL) break;
}
api->exec(argc, argv);
break;
}
}
}
}
The wo_update
function will take an exec
parameter, used to specify which asp api
to call, and a variable number of parameters based on the asp api
to be called.
We are going to focus on the notice
asp api
. The function responsible for performing the notice
action is called asp_notice
:
void asp_notice(int argc, char **argv)
{
char s[64];
char buf[2048];
if (argc != 1)
return;
snprintf(s, sizeof(s), "/var/notice/%s", argv[0]); [1]
if (f_read_string(s, buf, sizeof(buf)) <= 0) [2]
return;
web_putj(buf);
}
The function takes one argument. This function will take the argument passed (effectively a filename) and use it at [1]
to compose the string /var/notice/<argument passed>
. The composed string is used, at [2]
, as argument of the f_read_string
function, which will open the file and read its contents. Eventually, if the file exist, the asp_notice
function will print out its contents.
The problem is that from wo_update
up to the instruction at [2]
no sanitization of the filename parameter is performed. If the /var/notice
folder does exist, it would be possible to perform a path traversal to read any file in the file system.
2022-10-19 - Vendor Disclosure
2022-11-08 - Vendor Patch Release
2023-01-26 - Public Release
Discovered by Francesco Benvenuto of Cisco Talos.