За последний год я разобрал прошивки четырёх моделей TOTOLINK - и в каждой нашёл CGI-обработчик с классическим переполнением стека. CVE-2026-79911 в модели N600R не удивляет, но показательна: функция
setSystemConfig в /cgi-bin/cstecgi.cgi принимает параметр Hostname без проверки длины и кладёт его на стек через strcpy(). CVSS 9.3 (CRITICAL) по CVSS:4.0, удалённая эксплуатация без аутентификации, MIPS-архитектура без NX - полный набор для lab-walkthrough от распаковки firmware до reverse shell. Ниже - пошаговый разбор: реверс бинарника, стенд на QEMU, перезапись return address с переходом на shellcode (включая syscall cacheflush для синхронизации i-cache) и получение шелла.Анатомия CVE-2026-79911: CVSS-вектор и CWE
По NVD, уязвимость затрагивает TOTOLINK N600R с прошивкой 4.3.0cu.7647_B20210106. Уязвимый элемент - функцияsetSystemConfig в /cgi-bin/cstecgi.cgi. Манипуляция аргументом Hostname приводит к stack-based buffer overflow. NVD даёт два CWE:- CWE-121 (Stack-based Buffer Overflow) - описывает механизм: запись за границы буфера на стеке
- CWE-119 (Improper Restriction of Operations within the Bounds of a Memory Buffer) - родительский класс, отсутствие контроля границ при операциях с памятью
AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:PКлючевые компоненты:
| Компонент | Значение | Что это значит |
|---|---|---|
| AV:N | Network | Атака через сеть, физический доступ не нужен |
| AC:L | Low | Низкая сложность, специальных условий нет |
| PR:N | None | Аутентификация не требуется |
| UI:N | None | Действия пользователя не нужны |
| VC:H / VI:H / VA:H | High | Полная компрометация уязвимой системы |
| SC:H / SI:H / SA:H | High | Воздействие на смежные системы за роутером |
| E | Proof of Concept | Эксплойт раскрыт публично |
NVD прямо пишет: «The exploit has been disclosed publicly and may be used». CISA Vulnrichment подтверждает через SSVC: Exploitation -
poc, Automatable - yes, Technical Impact - total. Решение SSVC Track* - рекомендация отслеживать и готовить патч. На практике для устройства без активной поддержки вендора это читается проще: «изолировать или заменить».EPSS - 0.0064 (перцентиль 0.4844, ниже медианы). Формально вероятность массовой эксплуатации в ближайшие 30 дней невелика. Но для SOHO-роутеров EPSS обманчив: компрометация таких устройств редко попадает в корпоративные отчёты. Ботнеты, сканирующие интернет на открытые CGI-интерфейсы SOHO-железок, любят именно такие CVE - низкий EPSS, максимальный CVSS, никакой аутентификации. Подтверждённых данных об эксплуатации CVE-2026-79911 in the wild на момент написания нет, но я бы не расслаблялся.
Зачем атакующему этот роутер
По MITRE ATT&CK цепочка маппится на несколько тактик. Точка входа - Exploit Public-Facing Application (T1190, Initial Access): CGI-интерфейс доступен из сети. Дальше - Network Device CLI (T1059.008, Execution): после RCE атакующий получает shell. На этапе закрепления - Ingress Tool Transfer (T1105, Command and Control) для загрузки дополнительного payload и Firmware Corruption (T1495, Impact) для persistence через перезапись прошивки.Мотивация типична. Роутер превращается в прокси-ноду ботнета для DDoS или credential stuffing. Или становится pivot point: из домашней сети, где роутер - единственный периметр, атакующий добирается до всех устройств за NAT. Прошивка перезаписывается - бэкдор переживает перезагрузку. Двадцатидолларовая коробка, а ущерб - на порядки больше.
Анализ прошивки TOTOLINK N600R: извлечение cstecgi.cgi
Распаковка firmware через binwalk
Прошивка 4.3.0cu.7647_B20210106 - типичный образ для MIPS SoC. Распаковка стандартная:
Bash:
binwalk -eM N600R_4.3.0cu.7647_B20210106.bin
cd _N600R*.extracted/squashfs-root
file usr/sbin/cstecgi.cgi
# ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1
cstecgi.cgi - ELF под MIPS32 Little Endian (MIPSEL). На TOTOLINK-моделях этого поколения NX (Non-Executable stack) не реализован на аппаратном уровне, ASLR либо выключен, либо ограничен до 8-битной энтропии. Стек одновременно исполняемый и предсказуемый по адресам - условия для stack overflow эксплуатации, считай, идеальные.Реверс-инжиниринг setSystemConfig в Ghidra
Загружаем бинарник в Ghidra с MIPS-процессорным модулем, находимsetSystemConfig. Функция вызывается диспетчером CGI-обработчиков при POST-запросе с соответствующим значением topicurl в JSON-теле. Внутри - параметр Hostname извлекается из JSON через вызов, аналогичный cJSON_GetObjectItem(), и копируется в локальный буфер на стеке через strcpy(). Без проверки длины. Классика жанра - тот самый баг, который в учебниках показывают первым.В MIPS calling convention регистр
$ra (return address) сохраняется на стеке в прологе функции. При переполнении буфера последовательная запись за его границу перезаписывает сохранённый $ra. Когда функция выполняет jr $ra (return), управление уходит на адрес, который мы контролируем. Смещение от начала буфера до позиции $ra - константа для конкретной версии бинарника, определяется один раз в отладчике.Лабораторный стенд: эмуляция MIPS через QEMU
Для воспроизведения физический роутер не нужен. Бинарникcstecgi.cgi запускается через qemu-user с chroot в извлечённую файловую систему:
Bash:
echo -n '{"topicurl":"setSystemConfig","Hostname":"AAAA"}' | \
sudo chroot squashfs-root /usr/bin/qemu-mipsel-static \
-g 1234 \
-E REQUEST_METHOD=POST \
-E CONTENT_TYPE=application/json \
-E CONTENT_LENGTH=$(echo -n '{"topicurl":"setSystemConfig","Hostname":"AAAA"}' | wc -c) \
-E SCRIPT_NAME=/usr/sbin/cstecgi.cgi \
-E GATEWAY_INTERFACE=CGI/1.1 \
-E QUERY_STRING= \
/usr/sbin/cstecgi.cgi
-g 1234 открывает GDB-порт для удалённой отладки. В другом терминале подключаемся через gdb-multiarch с target remote :1234 и set architecture mips. Ставим breakpoint на setSystemConfig, подаём JSON через curl и смотрим, как Hostname ложится на стек.Нюанс (и он важный): CGI-бинарник тянет за собой
libcutil.so, libcommon.so и прочие shared libraries из прошивки. Если при запуске ловите segfault до обработки запроса - проверяйте наличие библиотек через readelf -d cstecgi.cgi. Иногда спасает LD_PRELOAD с заглушками для отсутствующих символов.Эксплуатация CVE-2026-79911: от crash до reverse shell
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
. Номер 4147 - стандартное значение
__NR_cacheflush для o32 ABI (см. arch/mips/include/asm/unistd.h); для n32/n64 номер другой, так что для конкретной прошивки сверьтесь с заголовками kernel/toolchain. Этот паттерн повсюду в реальных MIPS shellcode для роутеров: компактнее ROP-цепочки и не зависит от адресов функций в libc.После сброса кэша shellcode на стеке становится исполняемым. Типичный payload - reverse shell через
connect-back на IP атакующего. Размер shellcode для MIPSEL reverse shell - порядка 200 байт, в переполняемый буфер влезает с запасом.Структура payload
| Смещение | Содержимое |
|---|---|
| 0 - offset | Заполнение (мусор до $ra) |
| offset - offset+4 | Адрес shellcode на стеке (перезаписывает $ra) |
| offset+4 - ... | NOP sled + shellcode (cacheflush syscall 4147 + connect-back) |
Адрес стека предсказуем из-за отсутствия ASLR - определяется один раз в GDB через
info proc mappings или осмотр $sp в момент вызова setSystemConfig. В qemu-user адрес фиксирован между запусками; на реальном устройстве тоже стабилен, но стоит верифицировать через UART-консоль или повторный crash.Предусловия и ограничения
| Параметр | Значение |
|---|---|
| Модель устройства | TOTOLINK N600R |
| Версия прошивки | 4.3.0cu.7647_B20210106 |
| Архитектура | MIPS32 Little Endian (MIPSEL) |
| NX (non-executable stack) | Отсутствует |
| ASLR | Отключён или минимальный |
| Аутентификация | Не требуется (PR:N) |
| Сетевой доступ | HTTP к веб-интерфейсу роутера |
| Привилегии сервиса | Проверяйте на целевом устройстве (обычно root) |
| Статус патча | Отсутствует на момент написания |
Детектирование и митигация stack-based buffer overflow в TOTOLINK
На сетевом уровне эксплуатация выглядит как POST-запрос к/cgi-bin/cstecgi.cgi с аномально длинным значением Hostname в JSON-теле. IDS/IPS-правило: срабатывание на Content-Length к этому endpoint свыше типичного порога. Hostname роутера в нормальном режиме не превышает 64 символа - всё длиннее 256 байт уже подозрительно. Suricata-правило закроет вектор на уровне сети: alert http any any -> $HOME_NET any (msg:"TOTOLINK cstecgi.cgi setSystemConfig Hostname overflow attempt"; flow:to_server,established; http.method; content:"POST"; http.uri; content:"/cgi-bin/cstecgi.cgi"; http.request_body; content:"setSystemConfig"; content:"Hostname"; dsize:>256; sid:1000001; rev:1;).Митигация при отсутствии патча:
- Ограничить доступ к порту управления роутером через ACL - только определённые IP. Отключить WAN-доступ к админке (на TOTOLINK часто включён по умолчанию - проверяйте)
- Разместить роутер за дополнительный firewall, где HTTP-трафик к
/cgi-bin/фильтруется по Content-Length и payload-сигнатурам - Мониторить исходящие соединения: reverse shell с роутера выглядит как нетипичное TCP-соединение с management IP на внешний хост. Алерт на любые outbound-подключения, которых не было в baseline
- Замена устройства. Для N600R с этой прошивкой патча нет и, судя по всему, не будет. CISA выставила Automatable=yes с total impact. Если устройство на периметре - замена на модель с активной поддержкой вендора единственный надёжный вариант
strcpy() из HTTP-параметра в стековый буфер фиксированного размера - из модели в модель, из функции в функцию. Меняются имена параметров и названия обработчиков, но архитектура ошибки идентична. CWE-121 в setSystemConfig через Hostname - тот же класс бага, что и в десятках других CGI-обработчиков на тех же чипсетах. Это не единичный инцидент, а системная болезнь кодовой базы, которую вендор, судя по отсутствию патча, лечить не собирается.Отсутствие патча - не исключение, а правило для SOHO-устройств этого ценового сегмента. Роутер стоит условные $20, жизненный цикл поддержки заканчивается через год-полтора после выпуска, а firmware крутится в продакшене ещё лет пять. CISA выставила Automatable=yes - эксплуатация не требует ни навыков, ни ручного тюнинга, только HTTP-запрос нужной длины. Неудобная правда: пока SOHO-вендоры не начнут закладывать хотя бы stack canaries и минимальный ASLR в свои SDK, каждая следующая модель будет давать аналогичные CVE с аналогичным CVSS. Если хочешь повторить подобную цепочку на контролируемой инфре - категория pwn на HackerLab как раз под задачи с MIPS и бинарной эксплуатацией.