Talos Vulnerability Report

TALOS-2022-1642

FreshTomato httpd update.cgi directory traversal vulnerability

January 26, 2023
CVE Number

CVE-2022-38451

SUMMARY

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.

CONFIRMED VULNERABLE VERSIONS

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

PRODUCT URLS

FreshTomato - https://www.freshtomato.org/ QUARTZ-GOLD - https://www.siretta.com/products/industrial-routers/4g-lte-router/gigabit-ethernet-small-footprint-lte-router-eu/

CVSSv3 SCORE

6.8 - CVSS:3.0/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:N/A:N

CWE

CWE-22 - Improper Limitation of a Pathname to a Restricted Directory (‘Path Traversal’)

DETAILS

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.

TIMELINE

2022-10-19 - Vendor Disclosure

2022-11-08 - Vendor Patch Release

2023-01-26 - Public Release

Credit

Discovered by Francesco Benvenuto of Cisco Talos.