Извлечение контейнера закрытого ключа из APDU-трафика

Извлечение контейнера закрытого ключа из APDU-трафика Электронная цифровая подпись

Извлечение контейнера закрытого ключа из apdu-трафика

Уже скоро год с момента доклада , однако интересующиеся до сих пор пишут вопросы, что и послужило причиной написания этого поста.

Проблема с которой ко мне обратились – утилита dumpContfromAPDU.pl не дампит контейнер из правильно созданного с помощью Smartcard Sniffer -а лога команд и ответов APDU.
Причин такой неработы dumpContfromAPDU.plмогут быть две:
1.  используется отличная от имеющейся у меня на момент исследования модель токена – разные модели токенов имеют несколько разный набор команд APDU, поэтому скрипт не находит нужные регексы;
2. дамп не содержит пересылки контейнера.
Вообще, скрипт писался на скорую руку в качестве PoC исключительно для целей разовой демонстрации и делать из него полноценный инструмент “на все (ну, или, по крайней мере, на многие) случаи жизни” не планирую по нескольким причинам:
а)  наверно, это своего рода “хак” (реализация неавторизованного доступа), а распространять инструменты для неавторизованного доступа – неправильно;
б) лень.

В качестве компромисса – просто расскажу как извлечь контейнер из трафика APDU вручную и предположу почему это работает.

Как это сделать.
1. Получаем дамп Smartcard Sniffer-а, при выполнении операции Проверки (можно выполнить любую другую операцию, провоцирующую передачу ключа в приложение, например, вычисление электронной подписи), как это показано в видео .
2. Далее, как выше отмечено, скрипт dumpContfromAPDU.pl не работает, поэтому что-то запустить и получить контейнер – не получится :), но для анализа, традиционно на скорую руку, я написал другой скрипт – writeBinaryAPDU.pl ,  который делает элементарную вещь: дамп Smartcard Sniffer-а записывает в виде бинарных файлов диалога APDU между приложением и карточкой (токеном). Понятно, что диалог такой есть всегда, поэтому этот скрипт работает с любым токеном. В результате его работы появляется дериктория с именем эквивалентному времени ее создания, в которой лежат файлы вида “001_out(4)39_6A_42_32“, где
001 – идентификатор последовательности запрос-ответ;
out – означает, что эти байты передавались из карточки в приложение, соответственно, от приложения в карточку – будет “in”;
(4) – количество переданныхполученных байтов;
39_6A_42_32 – первые 4 байта.
3. Такие файлики (001_out(4)39_6A_42_32) далее смотрим глазами иили в шестрнадцатиричном редакторе. Кто такого редактора не имеет и никогда не планирует – можно использовать FAR .
4. Опытным путем установлено, что контейнер секретного ключа представляет из себя набор файлов с расширением .key (см. слайд 11 ):

  • header.key – файл, похоже, со всяким описанием, однако его целостность как-то контролируется, поэтому если его собрать не полностьюнеправильно контейнер работать не будет. О нем известно, что он содержит много информации, причем, в основном текстовой, через APDU передается порциями по 256 байт. Соответственно, в нашем дампе собираем в отдельную папочку все файлы вида №_out(256?)какие-то_байты. Я написал 256?не случайно, поскольку видел, как header.key передавался порциями по 253 байта, какая там логика выбора размера порций – не известно, но в любом случае эти порции будут радикально отличаться по размеру от всего остального трафика из карточки. Дополнительно к этим файлам надо обязательно добавить предыдущий порциям из 256 байтов ответ от карточки длиной 10 байт и с началом 30_82, а также, возможно, оставшийся “хвостик”, следующий за порциями по 256 байт (или 253 или еще сколько, но обычно – больше всех остальных, и равных).  Все эти файлы надо слить в один в порядке следования (поскольку вначале названия файла стоит номер последовательности – упорядочивание по алфавиту дает порядок следования) – это можно сделать утилиткой cat .
  • name.key – содержит имя контейнера, передаваемое обычно одной порцией (в рамках исследования я делал контейнер с очень длинным именем, это видно на видео, чтобы спровоцировать передачу имени контейнера в нескольких порциях – это удалось, передача проводилась аналогично передаче header.key: сначала первые 10 байт, затем – все остальное), искомый файл – следующего вида №_out(длина имени)30_длина имени_16_длина имени – 2. Интересен тот факт, что содержимое этого файла, в целом, не важно, поэтому можно сгенерить свой файл name.key, с соблюдением формата его первых четырех байт.
Читайте также:  Аккредитованные электронные торговые площадки и с какими ЭТП вы работаете? — Центр Сертификации СКБ Контур


В тех случаях, что я видел, можно игнорировать запросы к карточке №_in(размер)00_04*  и ответы на них. В некоторых случаях можно игнорировать и другие “стандартные” команды и ответы на них из спецификации GlobalPlatform .

Итак, собрав все 4 файлика, копируем их на флешку и проверяем контейнер, выполняя операцию “Проверка”, аналогично той, что делали в момент работы Smartcard sniffer-а (при этом уже никакой пароль на контейнер спрашиваться не будет). Если проверка не прошла, то надо попробовать различные “оконечные условия” для файла header.key – если после одинаковых порций вы добавляли “хвостик”, с порцией меньше предыдущих – попробуйте без него – если проверка снова неуспешна, добавьте еще следующую порцию (еще один “хвостик”) – в общем, поупражняйтесь с разными комбинациями порций файлов №_out(размер)* для сбора header.key.

Почему это работает (предположения).
Криптопровайдер ( CSP ) – это не только как реализована математика для выполнения различных криптографических преобразований, но и как ключи хранятся. Именно поэтому для хранения ключей на токене мы используем специальный “токенный” провайдер и т.п. 

Криптопровайдер КриптоПРО CSP (не КриптороПРО eToken CSP и не КриптоПРО Rutoken CSP!! – предположительно, на них не пройдет описываемая атака, но надо поисследовать…), умеет хранить хранить ключи в файликах, указанных выше, причем, не важно в какой среде – реестр ли Windows (посмотрите внимательно видео в районе 2:28, где видно как устроено хранилище в реестре 🙂 и сравните с упомянутым выше слайдом 11), флешка с файловой системой или токен используется. Работа с ключами происходит в приложении (криптопровайдере), а, следовательно, они туда передаются – поэтому они дампятся из трафика APDU.

Что же делать?
Да, как видите, недостаточно иметь токен, даже с отечественной криптографией на борту, надо еще иметь криптопровайдер, который для операций с ключом будет использовать не свои стеки и кучи, а бортовую криптографию токена, что прогарантирует выполнение вычислений с ключом внутри токена, что, в свою очередь, обеспечит отсутствие передачи ключа из токена, соответственно, его нельзя будет перехватить из трафика APDU.

Читайте также:  Приказ о наделении правом подписи 2020 и 2021 | Скачать форму, бланк

Конвертация в формат для openssl

Для взимодействия с API обычно используют openssl.

К сожалению, в сертификатах РФ используется свой стандарт шифрования (ГОСТ), поэтому обычный openssl не подходит, нужен патченный.

Копирование на файловую систему

Вначале создадим копию контейнера с токена на файловую систему.

Рутокен – российское средство аутентификации

Рутокен — это аппаратные и программные решения в области аутентификации, защиты информации и электронной подписи. Устройства Рутокен являются основными ключевыми носителями в массовых российских проектах, базирующихся на технологиях ЭП и инфраструктуре открытых ключей (PKI).

Снятие запрета на экспорт

В скопированном с токена контейнере все еще стоит флаг “экспорт запрещён”. Это естественно, ведь по сути директория-контейнер – это копия токена, с соответствующими флагами.

Оцените статью
ЭЦП Эксперт
Добавить комментарий