Автор: Мария Недяк
Вы наверняка видели в медицинском сериале, как интерны бьются над рентгеновским снимком пациента, а потом приходит их наставник и ставит диагноз по едва заметному пятнышку. В реальности такими остроглазыми диагностами становятся модели машинного обучения, применяемые в технологии medical imaging. Благодаря таким штукам можно гораздо быстрее выявить болезнь, например, определить, являются ли клетки на снимках опухолевыми или неопухолевыми.
Но есть одна проблема — в медицинских технологиях используются DICOM-протоколы, безопасность которых оставляет желать лучшего. О них и пойдет речь в этой статье.
Протокол DICOM и его слабые места
Коротко о самом протоколе
DICOM (Digital Imaging and Communication in Medicine) — протокол представления медицинских обследований и передачи их между различными компонентами. Этими компонентами могут быть:
- медицинское оборудование, которое непосредственно делает сканирование;
- DICOM-сервер — база данных для DICOM-файлов;
- DICOM-клиент — обычно это приложение для просмотра результатов медицинских обследований.
Протокол DICOM имеет две части:
- описание формата файла;
- описание сетевого взаимодействия.
Теперь к делу
Каждый DICOM-файл содержит информацию о пациентах и состоянии их здоровья — данные, которые требуют особой защиты. Именно поэтому я решила проверить реализации DICOM-протокола на уязвимости вместе с группой исследователей-энтузиастов AISec, которая занимается безопасностью в сфере машинного обучения.
Мы также изучили безопасность PACS (Picture Archiving and Communication System). Это такие системы, в которых результаты обследований хранятся в электронном виде. Они позволяют передавать снимки между врачами по сети. Да-да, благодаря PACS больше не нужно таскать с собой рентгеновские снимки в конверте, как мы привыкли.
DICOM-файл
DICOM-файл — изображение медицинского характера, сохраненное в формате DICOM. Этот формат — отраслевой стандарт для хранения и распространения медицинских снимков.
Помимо графических данных, DICOM-файлы могут содержать персональную информацию в виде атрибутов, позволяющих сопоставить изображение с конкретным человеком и идентифицировать пациента. К ним относятся пол, имя пациента, дата рождения и пр. Список возможных атрибутов и их описание можно найти в документации.
На рисунке показана структура DICOM-файла:
DICOM Network
Стандарт протокола довольно сложно и нудно описывает сетевое взаимодействие — мне до сих пор не удалось изучить его целиком. Но если говорить в общем, вот какие команды сетевого взаимодействия есть у DICOM-протокола:
Действие | Описание |
---|---|
C-ECHO | Тест соединения между двумя устройствами |
C-FIND | Поиск исследований на удаленном сервере |
C-GET, C-MOVE | Скачивание исследований с удаленного сервера |
C-STORE | Сохранение исследования на удаленном сервере |
Вот как выглядит процесс передачи результатов медицинских обследований по DICOM-протоколу
Немного статистики по DICOM-серверам в интернете.
Такие картинки-отчеты о сканировании генерирует Grinder Framework
Интересный факт: когда мои коллеги из AISec проводили сканирование в 2019 году, то доступных серверов было меньше тысячи. В 2020 году же их оказалось около 2700.
Большинство хостов в сети настроены таким образом, что любой может установить с ними соединение. Давайте разберем пример, как просто получить исследование с удаленного сервера из сети. Для этого воспользуемся утилитами findscu и getscu из DCMTK — набора библиотек и приложений, реализующих большую часть стандарта DICOM.
Первой командой получаем список всех доступных исследований на сервере.
$ findscu -aet <AE Title> -P -k PatientName="*" <host> <port>
С ключом -aet
в запросе передаем название Application Entity Title
. Обычно этот тайтл требуется, когда нужно разграничить доступ к изображениям при использовании одного DICOM-сервера разными PACS. Это, своего рода, идентификация клиента. Но проблема в том, что тайтлы на многих серверах настроены по умолчанию. Это значит, подобрать его можно, перебирая дефолтные значения от разных разработчиков PACS и DICOM-серверов.
С ключом -k
передаем фильтр "PatientName=*"
, который позволит показать любое доступное исследование на сервере.
Пример вывода команды findscu
Следующей командой скачиваем нужное нам исследование или все исследования сразу.
$ getscu -aet <AE Title> -P -k PatientName="John Doe" <host> <port>
Значения ключей в команде аналогичны предыдущей.
Пример исследования, скачанного с удаленного сервера DICOM
Вот так с помощью двух команд можно скачать данные с удаленного DICOM-сервера при наличии одного из условий:
Application Entity Title
не задан,Application Entity Title
установлен по умолчанию, поэтому его удалось подобрать.
Далее рассмотрим популярные инструменты и реализации протокола и найденные в них недостатки.
Реализации протокола DICOM
SimpleITK
SimpleITK — реализация протокола, которая используется в одном из крупных проектов в области medical imaging NVIDIA CLARA.
Для поиска уязвимостей в ней использовался фаззинг AFL со словарем. В результате мы наткнулись на переполнение кучи. Попытки эксплуатации привели к обнаружению более простой уязвимости — переполнению буфера через поле PatientName
. Причем для переполнения буфера было достаточно создать файл с длиной имени пациента свыше 512 байт.
В ответ на репорт о переполнении кучи разработчик просто поправил файл, демонстрирующий уязвимость, чтобы он корректно обрабатывался библиотекой :)
Чем кончилось: в конце концов мы друг друга поняли, и вендор быстро исправил обе уязвимости.
DCMTK
DCMTK (DICOM Toolkit) — самая старая реализация DICOM-протокола. Она включает набор инструментов для работы с протоколом: парсеры DICOM-файлов в разных форматах и из разных форматов, а также утилиты для взаимодействия с DICOM-сервером по сети.
XXE в xml2dcm
Парсер xml2dcm конвертирует результаты медицинского обследования из формата XML в DICOM.
В xml2dcm мы нашли уязвимость к самой простой XXE-атаке: создаем XML-файл с внешней сущностью в имени пациента и на выходе получаем DICOM-файл с содержимым /etc/passwd
.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
…
<element tag="0010,0010" vr="PN" vm="1" len="32" name="PatientName">&xxe;</element>
…
Чем кончилось: данную уязвимость вендор устранил.
Небезопасные функции xml2dcm
По аналогии с external entities в XML, cама по себе утилита xml2dcm позволяет создавать DICOM-файлы c содержимым других файлов внутри. Это удобно, потому что не нужно писать данные в XML-файл — достаточно указать в теге PixelData
путь к файлу, из которого нужно подгрузить данные при конвертировании.
<element tag="7fe0,0010" vr="OW" vm="1" name="PixelData" loaded="no" binary="file">/etc/passwd</element>
Если в теге PixelDatа
указать путь к любому файлу в системе, то после обработки утилитой xml2dcm мы получим DICOM-файл с его содержимым.
Чем кончилось: эту функцию невозможно отключить никаким флагом, а на доработку парсера xml2dcm вендор не согласился :(
DoS в парсерах DICOM-файлов
Мы тестировали парсеры из DCMTK при помощи фаззинга AFL и libFuzzer. Результат — DoS-утилиты xml2dcm и dcm2xml.
Чем кончилось: вендор исправил найденные ошибки.
DoS в dcmqrscp-сервере
DCMTK также предоставляет реализацию DICOM-сервера dcmqrscp. Тестирование безопасности DICOM-сервера dcmqrscp было проведено с помощью фаззинга, в результате которого был обнаружен DoS.
Фаззинг проводился при помощи AFLNet. Поддержку протокола DICOM я добавила в официальный репозиторий AFLNet, если кому-то захочется пофаззить другие DICOM-серверы.
Чем кончилось: вендор исправил ошибку реализации.
Приложения medical imaging
ORTHANC
В ходе исследования мы затронули приложение ORTHANC. Этот продукт очень прост в настройке и использовании: он предоставляет веб-обертку для просмотра DICOM-файлов, и для работы с DICOM-протоколом требуется только браузер.
ORTHANC используют в здравоохранении, в различных университетах и госпиталях, с его помощью проводятся исследования в области машинного обучения medical imaging (раз и два).
Открытые серверы ORTHANC в сети
Небезопасное API
Сервер ORTHANC открыт к сообществу разработчиков и предоставляет REST API для написания различных плагинов. Если взглянуть на список доступных методов, можно заметить интересные методы для перезагрузки и выключения сервера, а также метод с названием execute-script
.
Он принимает на вход скрипты на lua и без какой-либо валидации выполняет их на сервере. Чтобы убедиться в этом самостоятельно, посмотрите исходный код ORTHANC.
Чем кончилось: раньше этот метод был включен по умолчанию в конфиге Orthanc, но, к счастью, недавно вендор догадался его отключить. Однако в сети до сих пор можно наткнуться на Orthanc-серверы с работающим методом execute-script
.
Уязвимость аутентификации к CSRF-атаке
Метод execute-script
является небезопасным. Разработчик ORTHANC решил эту проблему при помощи аутентификации, чтобы выполнять такие запросы могли только зарегистрированные пользователи. Но по умолчанию аутентификация отключена при работе с ORTHANC-сервером с официального сайта.
В докере от разработчика уже включена аутентификация по умолчанию. Это здорово, если бы не следующая проблема: данная система аутентификации уязвима к CSRF-атаке. Достаточно создать страничку со следующим содержанием и отправить ее пользователю:
<html>
<body>
<form action="http://<host>:8042/tools/execute-script" method="POST" enctype="text/plain">
<input type="hidden" name="cmd" value="'mkdir /tmp/testCSRF';os.execute(cmd)"/>
<input type="submit" value="Submit request" />
</form>
</body>
</html>
Когда пользователь открывает страницу, на сервер отправляется команда, запускающая выполнение произвольного кода.
Ответ вендора на запрос исправления данной уязвимости меня удивил: оказывается, ORTHANC — это микросервис, поэтому и о безопасности среды, где вы его разворачиваете, извольте позаботиться сами. То есть и механизм аутентификации мы сами должны написать? И догадаться о том, что поставляемый вендором механизм аутентификации лишь создает иллюзию безопасности и надежности, но на самом деле бесполезен?
Ответ вендора
BTW: кеш гугла показал, что приписку в документации о CSRF вендор сделал после моего репорта об уязвимости. И, конечно же, вряд ли он известил тех клиентов, которые уже пользуются их «микросервисом» и верят в его надежность.
Страница документации после ответа вендора на репорт об уязвимости
Страница документации из кеша гугл за пару дней до репорта не содержит каких-либо упоминаний CSRF
Чем кончилось: вендор так ничего и не предпринял для устранения данной уязвимости, только дополнил документацию.
Заключение
То, как просто найти уязвимости в medical imaging и как забавно вендоры реагируют на баг-репорты, показывает слабый уровень защищенности таких технологий. Чтобы они стали безопасными, над ними еще работать и работать.
Напоследок оставлю табличку со всеми описанными в статье багами.
Vendor | Product | Weakness |
---|---|---|
SimpleITK | ImageSeriesReader | Heap-buffer-overflow |
SimpleITK | ImageSeriesReader | Buffer-overflow |
Orthanc | Orthanc | CSRF with remote code execution |
DCMTK | xml2dcm | XXE |
DCMTK | xml2dcm | DoS |
DCMTK | xml2dcm | File read functionality |
DCMTK | dcm2xml | DoS |
DCMTK | dcmqrscp | DoS |
Также подробная информация лежит на github.
EVolans
А может кто пояснить зачем защищать сам протокол, если например ЦАМИ (центральный архив медицинских изображений) попадает под 187-фз по умолчанию и защищены будут все сегменты сети, т.е. чтобы добраться до протокола, надо сначала попасть в защищенную сеть. Да и без этого — все что подключено к ЕГИСЗ (единая государственная информационная система здравохранения) уже находиться в защищеннйо сети.
serbod
А зачем в квартире замок, ведь в подъезде уже есть надежная железная дверь с электронным замком? =)
BiZone_team Автор
В статье приведена статистика по открытым серверам DICOM, которая показывает, что даже в России не все серверы находятся в закрытой сети. К тому же мы рассматриваем DICOM-протокол не только в контексте законодательства РФ.
EVolans
По моему это говорит не о проблеме DICOM, а о проблеме отстутствия какой либо защиты персональных и прочих данных во всем мире.
D3fl4t3
Нельзя ограничиваться только лишь бумажной безопасностью. Правильная модель угроз предполагает, что система не может быть идеальной, поэтому единственный выход, особенно в таких критичных системах — эшелонированная защита на всех уровнях.