Возможности Приложение Тарифы API Демо Блог Презентация Документация Запросить демо
← Все статьи

Посмотрели на свою админку глазами реверс-инженера: что инструмент нашёл и что пропустил

Платформа · 7 минут

Страница входа в биллинг выглядит просто: логин, пароль, кнопка. Но браузер перед показом этой формы получает гораздо больше, чем видит человек, и получить это может любой, у кого есть адрес панели. Мы решили посмотреть, что именно там лежит, и заодно проверить новый инструмент для реверс-инжиниринга — REA.

Страница входа в панель СмИТ Биллинг: снаружи только форма
Снаружи только форма. Внутри, как выяснилось, 119 скриптов

Что такое REA и как мы его запускали

Реверс-инжиниринг — это разбор программы, у которой нет исходного кода: понять по готовому файлу, как она устроена. REA собирает для этого разные инструменты под одну команду. Он читает JavaScript сайтов и приложений, а скомпилированные программы разбирает через подключаемые движки: Ghidra, Hopper, Kuna или IDA. Им можно пользоваться из терминала или подключить к ИИ-агенту. Мы брали версию 6.8.0 из npm. Документация проекта описывает более новую ветку, так что часть ограничений из этой статьи там может быть уже снята.

Мы проверяли только свою систему и только пассивно. REA читал код уже открытой вкладки браузера: ни формы, ни кнопки он не трогал и к API сам не обращался. Браузер запускали отдельный, с пустым профилем, чтобы в анализ не попали рабочие сессии.

flowchart LR
  a1["Отдельный браузер<br/>с пустым профилем"] --> a2["Страница входа"]
  a2 --> a3["REA читает<br/>код вкладки"]
  a3 --> a4["Вход делает человек"]
  a4 --> a5["REA читает<br/>страницу после входа"]
  a5 --> a6["Сверка с кодом<br/>и выводы"]

Сравнили две страницы: форму входа и профиль пользователя после авторизации. Другие разделы панели в тест не вошли. Анализ занял меньше сорока секунд на страницу.

Сводка REA: 119 и 126 скриптов, 7 и 13 адресов API, 0 маршрутов
Сводка по двум страницам

Ноль маршрутов в сводке — ожидаемый результат. Страницы панели собирает сервер, а поиск маршрутов в REA рассчитан на одностраничные приложения.

Что видно до входа

Форме входа нужны два поля, проверка и пара стилей. А браузер получает 119 скриптов: 90 файлов и 29 блоков прямо в странице. Среди них окна сделок, выбор тарифов, телефония, почта. Страница входа построена на том же общем шаблоне, что и вся панель, поэтому загружает её целиком.

В этих скриптах REA нашёл семь внутренних адресов. Два относятся ко входу по отпечатку или аппаратному ключу, и они форме нужны. Остальные пять связаны с почтой, уведомлениями, телефонией и настройками интерфейса. Само по себе это не уязвимость: адрес ещё не даёт доступа, если сервер проверяет права на каждый запрос. Но публичной странице незачем показывать эти пять адресов, а браузеру незачем разбирать около 1,6 МБ кода (до сжатия) при каждом открытии формы. Лёгкий отдельный шаблон решил бы обе задачи. Для сравнения, страница входа в личный кабинет абонента сделана именно так: 7 скриптов и 30 КБ кода против 119 скриптов и 1,6 МБ у панели.

Важная оговорка: права доступа мы в этом тесте не проверяли и ни один из найденных адресов не вызывали. Это был не аудит безопасности, а знакомство с инструментом.

Самое полезное: что инструмент пропустил

После входа скриптов стало 126, а найденных адресов — 13. Выглядит убедительно, поэтому мы сверили результат с самим кодом: взяли три скрипта, которые появляются только после авторизации. В них четыре обращения к серверу через fetch, а REA нашёл одно.

Причина оказалась простой. Вот так инструмент адрес видит (адреса в примерах упрощены):

fetch('/api/share/', { method: 'POST' })

А вот так уже нет, хотя для человека разницы никакой:

var URL = '/api/balance/';
fetch(URL, { credentials: 'same-origin' });

В одном из старых файлов нашлось ещё шесть вызовов через jQuery ($.ajax, $.get, $.getJSON), и ни один адрес оттуда в список не попал. Почему, мы не выясняли: либо инструмент не понимает jQuery, либо помешал частичный разбор этого файла, о котором ниже.

Отсюда главный вывод этого теста. Отчёт такого инструмента показывает то, что он нашёл, но не доказывает, что больше ничего нет. Список из 13 адресов выглядит законченным, а на проверенном участке инструмент увидел один адрес из четырёх.

Три файла — маленькая выборка, поэтому мы повторили разбор на всех 128 собственных скриптах панели. В графе запросов REA оказалось 90 обращений к серверу, и только в пяти адрес виден прямо. Обычный поиск по тексту тех же файлов находит 95 разных адресов. Сравнение не совсем честное: граф REA упёрся в собственный лимит в 100 000 узлов. Но сам инструмент предупреждает об этом в отчёте: то, чего он не видит, нельзя считать отсутствующим.

Для настоящей инвентаризации API надёжнее взять список маршрутов из самого приложения, а находки инструмента использовать как дополнение. В биллинге таких маршрутов больше полутора тысяч.

Находка в одну строку

Одна польза всё же обнаружилась сразу. REA пометил один из наших старых скриптов как «разобранный частично». Мы проверили: файл корректный, браузер и Node.js принимают его без ошибок. Инструмент оказался строже браузера, а споткнулся о строку вроде этой:

$.map(interfaces_list, function (interface, v) { /* ... */ });

interface — зарезервированное слово в строгом режиме JavaScript и в ES-модулях. Сегодня код работает, потому что файл подключён по-старому. Но стоит перевести его на модули или включить строгий режим, и скрипт перестанет загружаться. Формально пометка оказалась ложной тревогой, но указала на настоящее хрупкое место. Исправляется переименованием параметра. Такие места хорошо чинить заранее, а не в день большого обновления.

А если исходников нет совсем

Панель написана нами, поэтому её код и так у нас есть. Интереснее другое: REA умеет разбирать и готовые программы. Мы взяли системную утилиту hostname.exe, у которой нет ни исходников, ни имён функций, и попросили восстановить логику.

Псевдокод, восстановленный из hostname.exe
Восстановленный псевдокод: разбор аргументов, запрос имени компьютера, вывод

Результат совпал с реальным поведением программы: при /? или -? выводится справка, при неизвестном аргументе — ошибка, без аргументов — имя компьютера. А на одноимённой утилите для Linux два разных движка, Ghidra и Hopper, независимо указали на одну и ту же главную функцию.

Оператору связи это может пригодиться, например, чтобы понять, что делает служебная утилита оборудования без документации. Разбирать чужие программы стоит только если это разрешают лицензия и закон. Свои — пожалуйста.

Какой движок где работает

Здесь нас ждал самый практичный сюрприз: возможности инструмента сильно зависят от операционной системы.

ДвижокWindowsLinuxЧто разбираетАнализ небольшого файла
Ghidraда, только PEдаPE, ELF, Mach-O10–30 с
KunaнетдаELF, Mach-Oоколо 2 с
Hopperнетда, демо-режимELF (больше не проверяли)около 4 с
IDAне проверялине проверяли——

PE — это программы для Windows, ELF — для Linux, Mach-O — для macOS. Для Linux-программ на Windows нужен контейнер или отдельная машина с Linux: мы проверяли их в одноразовом контейнере. Запуск на macOS мы не проверяли.

rea doctor: какие движки готовы к работе
Встроенная проверка готовности. Здесь всё уже настроено, а до этого она точно назвала библиотеку, которой не хватало для Hopper

У инструмента есть и другие слабые места. Два из пяти реальных файлов JavaScript мы не дождались: один за 80 секунд, другой за 280. Дело не в размере: файл на 647 КБ прошёл за 15 секунд, а на 425 КБ не закончился и за 80. Причину мы не выяснили. При этом ведёт себя REA аккуратно: по истечении времени отдаёт понятную ошибку и частичные данные, зависших процессов не остаётся.

При подключении к ИИ-агенту REA по умолчанию отдаёт описание 229 инструментов объёмом 3,4 МБ. Настройку лучше сразу менять: с отключёнными схемами ответов описание сжимается до 295 КБ. Сам разбор той же утилиты через агента занял около минуты и стоил 30–50 центов, результат оказался верным. Но в одном из ответов агент добавил деталь, которой в коде нет, так что его выводы тоже надо проверять.

Что мы вынесли

Как это работает в СмИТ Биллинге

Панель — серверное приложение: страницы собирает сервер на общем шаблоне, поэтому страница входа и получила те же скрипты, что и рабочие разделы. Адрес в коде страницы сам по себе ничего не открывает. Но проверяет ли сервер права на каждом адресе, по скриптам в браузере узнать нельзя: для этого нужны отдельный разбор серверного кода и проверка запросов. REA такой работы не делает, и его отчёт нельзя считать заключением о защищённости.

Посмотреть на своих данных

Покажем платформу на живом стенде и разберём ваш случай. Или спросите ассистента прямо сейчас — он отвечает по документации и настройкам.

Поделиться ВКонтакте Telegram

Читайте также

7 мин
Платформа

CPU 132 %: один недостающий индекс и 800 миллионов строк каждые пять минут

Красный треугольник «CPU 132.3%» в шапке биллинга. Служебная задача каждые пять минут 500 раз читала таблицу сессий целиком. Как нашли её меньше чем за полчаса и почему лечением стал один индекс: запрос — 0,1 мс, нагрузка — вдвое ниже.

Читать →
9 мин
Платформа

Счётчик провалов врал: как мы проверяем ИИ-помощника

Счётчик «бот не смог» показывал 83 диалога, настоящих было 5. Как нашли ошибку в подсчёте, какие пять провалов оказались реальными и как на 24 письмах-заявках сравнили 11 моделей: точность 76 → 93 %, выдуманные данные исчезли.

Читать →
7 мин
Платформа

Закрытый контур: биллинг, который сам не ходит наружу

Одна настройка на сервере оператора, сторож исходящих соединений с журналом, только ключ и домен на сервер лицензий, ИИ выключен или своя модель, файлы у оператора — и протокол, по которому служба безопасности проверит это сама.

Читать →