В Казахстане многие информационные системы не корректно интегрированы с NCALayer и в результате поддерживают только файловые хранилища ключей ЭЦП (читателям, интересующимся примерами таких сервисов, рекомендую изучить цикл статей Доска почёта ЭЦП посвященный анализу проблем с реализацией поддержки ЭЦП в информационных системах). Тех, кто предпочитает пользоваться защищенными носителями (картами и токенами, НУЦ поддерживает несколько: https://pki.gov.kz/docs/nl_ru/smartcards/), это сильно раздражает, так как им приходится выпускать временные сертификаты на файловую систему для того, чтобы работать с такими порталами. Для меня последней каплей стало то, что в недавно переработанной системе https://hr.enbek.kz (государственная система регистрации и учета трудовых договор) поддержка защищенных носителей так и не была реализована.
В этой заметке я расскажу как технически подкованные пользователи могут обходить ограничения в поддержке носителей путем запуска локального прокси и модификации отправляемых в NCALayer команд на лету.
Теория
Информационные системы на базе веб технологий взаимодействуют с NCALayer по WebSocket с помощью сообщений в формате JSON. Ознакомиться с командами можно в интерактивной документации по приложению KAZTOKEN mobile (либо можно получить SDK НУЦ, но, к сожалению, там есть только примеры). Поддержка защищенных носителей сводится к тому, что нужно:
отправить
kz.gov.pki.knca.commonUtils.getActiveTokens
, в ответ получить список типов хранилищ, экземпляры которых в данный момент доступны для использования;в том случае, если список не пуст, определить (к примеру спросить у пользователя) какой тип использовать;
передавать в последующие команды тип хранилища.
Разработчики некоторых информационных систем халтурят, пропускают первые два пункта и далее всегда передают константу "PKCS12"
, то есть файловое хранилище. Это приводит к тому, что пользователь не может воспользоваться ключами ЭЦП на защищенном носителе, а таких пользователей, судя по статистике НУЦ РК, довольно много:
Более того, в руководстве по получению сертификатов НУЦ РК явно рекомендуется использовать защищенные носители:
Внимание! Хранилище «Персональный компьютер» является небезопасным. Рекомендуем использовать защищенный носитель ключевой информации для снижения риска компрометации ключей ЭЦП.
Таким образом для того, чтобы заставить не качественно разработанный портал поддерживать защищенные носители, нужно в сообщениях, отправляемых из JS кода этого портала в сторону NCALayer, заменять подстроку "PKCS12"
на константу интересующего носителя. Я пользуюсь устройствами KAZTOKEN, поэтому буду подставлять константу "AKKaztokenStore"
.
Практика
В качестве браузера я использую Firefox, наверняка можно использовать и другие, но так как я пользуюсь именно им, то инструкцию предоставлю для него.
Для модификации команд на лету я воспользуюсь утилитой mitmproxy.
Модификацию будет выполнять следующий скрипт (KAZTOKENify.py
, за основу взят https://github.com/mitmproxy/mitmproxy/blob/main/examples/addons/websocket-simple.py):
import re
from mitmproxy import ctx, http
def websocket_message(flow: http.HTTPFlow):
assert flow.websocket is not None
message = flow.websocket.messages[-1]
if message.from_client:
message.content = re.sub(rb"PKCS12", b"AKKaztokenStore", message.content)
Для выборочного использования прокси буду использовать файл следующий автоматической настройки прокси (Proxy Auto-Configuration (PAC)) proxy.pac
:
function FindProxyForURL(url, host) {
if (url.indexOf('wss://127.0.0.1:13579') == 0 || url.indexOf('wss://localhost:13579') == 0 ||
url.indexOf('https://127.0.0.1:13579') == 0 || url.indexOf('https://localhost:13579') == 0) {
return "PROXY 127.0.0.1:8080";
}
return "DIRECT";
}
Для настройки нужно выполнить шаги:
Скачать сборку mitmproxy для своей ОС, распаковать архив.
Создать текстовый файл
KAZTOKENify.py
в папке с утилитой mitmproxy, вставить в него скрипт.Запустить
mitmproxy --allow-hosts 127.0.0.1 --allow-hosts localhost --ssl-insecure --scripts KAZTOKENify.py
(прокси будет вскрывать только трафик на127.0.0.1
иlocalhost
, а так же не будет проверять TLS сертификат сервера, это проще чем настраивать доверие к сертификату NCALayer).Создать текстовый файл
proxy.pac
, вставить в него соответствующий код.В браузере открыть Настройки -> Параметры сети -> Настроить…, выбрать URL автоматической настройки прокси и указать путь к файлу
proxy.pac
в следующем виде:file:///home/user/folder/proxy.pac
.В браузере открыть
about:config
и установитьnetwork.proxy.allow_hijacking_localhost
вtrue
(иначе Firefox не будет использовать прокси для127.0.0.1
иlocalhost
).В браузере открыть http://mitm.it/, установить сертификат УЦ mitmproxy (сертификат УЦ генерируется на каждом ПК свой в отличие от NCALayer, который требует от всех доверять одному сертификату).
В браузере открыть https://127.0.0.1:13579, удостовериться в том, что браузер видит NCALayer в соответствии с инструкцией (для TLS будут использоваться сертификаты УЦ mitmproxy).
Готово, теперь можно пройти на https://hr.enbek.kz и подписать что-нибудь, NCALayer будет отображать интерфейс работы с устройствами KAZTOKEN, а не с файловой системой.
Либо можно попробовать на странице интерактивной документации KAZTOKEN mobile. Для этого, к примеру, можно выбрать kz.gov.pki.knca.commonUtils.getKeyInfo
, заменить в ней AKKaztokenStore
на PKCS12
и отправить, NCALayer все равно будет работать с KAZTOKEN.
Заключение
Буду очень признателен каждому читателю, который расскажет своему знакомому разработчику о том, что НУЦ выпускает сертификаты не только на файловую систему!
А разработчикам рекомендую использовать JS библиотеку ncalayer-js-client в надежде на то, что более простой инструмент для работы с NCALayer оставит больше времени и сил на проработку нюансов интеграции.
Комментарии (4)
saipr
15.08.2022 22:50К сожалению у меня нет вашего токена.
А так можно было бы с ним поиграться в утилите cryptoarmpkcs и ответить на вопрос up40k :чем технически казтокен отличается от рутокена-эцп?
up40k
Вопрос немного оффтоп: чем технически казтокен отличается от рутокена-эцп? На вид это одинаковые устройства (с разными шильдиками), NCALayer определяет рутокен как казтокен и предлагает использовать его как хранилище. Как я понимаю, вся работа с ключами в обоих случаях происходит по PKCS#11, поэтому разработчики сочли достаточным определять базовый id устройства, вне зависимости от бренда, и всё считать казтокеном.
Я не рискнул выпускать сертификаты на рутокен, но, думаю, ничего бы не сломалось.
И вдогонку ещё вопрос, для меня уже неактуальный, но разобраться всё ещё хочу. Вот вы в статье приводите цифры от НУЦ по количеству защищенных хранилищ по годам. Вы же понимаете, что это очень хитрые цифры, и откуда они берутся?) Не все, естественно, но, имхо, большая часть таких носителей - это смарткарты на удостоверениях личности. Гражданин очередной раз меняет документ, ему выпускают ключ и заботливые сотрудники ЦОНа устанавливают в качестве пин-кода год рождения гражданина. Вернее, он сам без задней мысли вводит свой год рождения на пинпаде, когда сотрудник его об этом просит. Не знаю, как сейчас обстоят дела с этим регламентом (есть надежда, что поменяли в лучшую сторону, так как наконец-то в этом году появились правила по силе пароля для файлового хранилища, может, и с пинами объяснили служащим на местах, как правильно) - но с самого появления смарткарт на удостоверениях и вплоть до 2019 года (я тогда в последний раз его получал) пины у граждан соответствовали годам рождения. Естественно, считать такой носитель защищенным нельзя. Более того! Поменять пин мне так и не удалось, ни через ЦОН, ни через 1414, ни через попытки общения с картой по PC/SC. То ли это аппаратное ограничение, то ли я был не слишком настойчив. Единственный выход в такой ситуации - отзыв сертификата в НУЦ.
Есть еще на что посетовать, например, с текущей версией eGov mobile, но это прям совсем оффтоп, не буду)
up40k
Так. Прошу прощения! Перешел по ссылке на статистику, удостоверения личности там отдельной таблицей. Так что ваши предпосылки вполне оправданы.
vsenko Автор
По поводу удостоверений личности - на мой взгляд даже в таком формате, который Вы описываете, удостоверение личности лучше файловой системы, так как файл можно скопировать (то есть копия файла может быть у злоумышленника в то время, когда пользователь об этом ничего не подразумевает), а закрытый ключ из удостоверения личности не получится (по крайней мере нам так говорят).
По поводу того, что NCALayer воспринимает другие устройства как KAZTOKEN, к сожалению ничего пояснить не смогу, тут нужно смотреть код NCALayer. С практической точки зрения KAZTOKEN - это сертифицированные (по СТ РК 1073-2007) в РК устройства.