Исследователь компании «Уральский Центр Систем Безопасности» Андрей Жуков обнаружил ряд уязвимостей в популярной SCADA-системе «Intouch», произведённой французской компанией «Sсhneider Electric» – мировым экспертом в управлении энергией и автоматизации.
Система Intouch – наиболее используемая HMI/SCADA система в мире. Представляет собой программное обеспечение для сбора данных, оперативного контроля и управления автоматизированными устройствами и технологическими процессами.
Уязвимости были найдены в ходе длительного изучения алгоритмов работы сервиса aaLogger.exe, представляющем из себя сетевой сервис, работающий по технологии DCE/RPC.
В процессе исследования возникли некоторые сложности:
- необычная реализация DCE/RPC-интерфесов. При написании клиент-серверного приложения по технологии DCE/RPC программист создает idl-файл с описанием интерфейсов и структур, после чего специальный компилятор midl генерирует на основе него C-код – обёртку, который даёт иллюзию удалённого вызова процедур. Параметры генерации кода различаются и в данном случае использовался так называемый inline stubs режим (midl /Os), при котором форматная строка не содержит полного описания интерфейсов функций-обработчиков DCE/RPC-вызовов. Ни одно из публично доступных инструментов не смогло автоматически извлечь прототипы исследуемых функций;
- сложная реализация DCE/RPC-вызова при фаззинге. Большая часть DCE/RPC-интерфейсов использовала т.н. явный context_handle (структура, наподобии cookie, в которой хранится состояние между вызовами), который предварительно нужно было инициализировать через вызов DCE/RPC-процедуры c id=0 на соответствующем интерфейсе;
- динамически назначаемый порт. Зачастую DCE/RPC сервисы работают через End Point Mapper, сервис, который назначает динамический (постоянно меняющийся) порт. При подготовке к фаззингу был модифицирован код исследуемого сервиса, реализующий создание DCE/RPC-интерфейсов на фиксированном порту;
В результате было получено около 90 функций на 8 различных DCE/RPC-интерфейсах. В ходе продолжительного фаззинга было выявлено 5 классов уязвимостей:
1) Null pointer dereference. Вызовы с номерами 3-16 на интерфейсах ea3669c2-3bde-4cc1-b34a-77708ce6b37c, 57810394-0d55-4e58-a04c-d71ab05575d6 и 65d6a0c8-7e7b-4c9b-ba42-801d23640739 без предварительного вызова 0 DCE/RPC-процедуры приводили к ошибке разыменования нулевого указателя из-за того, что структура context_handle, содержащая базу LogReader.dll и указатель на объект CreateLogReader не была полностью проинициализирована.
2) Integer overflow. Вызов номер 1 на интерфейсах ea3669c2-3bde-4cc1-b34a-77708ce6b37c, 57810394-0d55-4e58-a04c-d71ab05575d6 и 65d6a0c8-7e7b-4c9b-ba42-801d23640739, предназначенный для получения имени ПК, ни как не проверял на допустимость значение длины. Значение длины подставлялось в функцию _wcsncpy_s(dst, count, src, count-1), принимающем count как беззнаковое целое. Таким образом 0 значение длины превращалось в 4294967295 и при попытке добавления символа конца строки по этому смещению приводило к аварийному завершению работы программы.
3) Resource consumption. Вызов номер 11 на интерфейсах ea3669c2-3bde-4cc1-b34a-77708ce6b37c, 57810394-0d55-4e58-a04c-d71ab05575d6 и 65d6a0c8-7e7b-4c9b-ba42-801d23640739 интерпретировал один из аргументов как количество некоторых объектов, которые необходимо создать. Слишком большое число объектов приводило к переполнению динамической памяти, в следствии чего программа потребляла всё доступное ей количество виртуальной памяти и переставала отвечать на запросы.
4) Stack buffer overflow. Процедуры номер 5 и 11 на интерфейсах ea3669c2-3bde-4cc1-b34a-77708ce6b37c, 57810394-0d55-4e58-a04c-d71ab05575d6 и 65d6a0c8-7e7b-4c9b-ba42-801d23640739 для копирования переданной строки использовали собственную реализацию функции wmemcpy(). Функция, предназначенная для копирования unicode-символов длиной 2 байта, вызывалась для копирования ascii-символов. Рассогласование типов wchar и char приводило к тому, что функция записывала ровно вдвое больше данных, чем было положено. Этого оказалось достаточным чтобы достать до SEH и адреса возврата – этого достаточно для выполнения произвольного кода.
5) Создание произвольных папок. Один из DCE/RPC-вызовов позволяет создание произвольных папок на сервере.
Сразу после обнаружения уязвимости, информация была передана в Schneider Electric. В течение 8 месяцев было выпущено и протестировано 2 версии патча, устраняющих уязвимости.
Найденным уязвимостям присвоены номера CVE-2017-9631 (1), (2), CVE-2017-9627 (3), CVE-2017-9629 (4). Уязвимость (5) не может быть исправлена из-за архитектурных особенностей SCADA системы в ближайшее время.