Почти год назад на Хабрахабре появилась статья "
Исследование защищенности карты Тройка", в которой было подробно описано устройство проездных билетов и векторы атаки на систему оплаты общественного транспорта в Москве. Ещё тогда, вдохновившись прочитанным, мне захотелось попробовать применить описанные в статье приёмы к петербургскому аналогу Тройки — карте Подорожник, которая используется для оплаты поездок в общественном транспорте города.
Как и в оригинальной статье, спешу предупредить читателей:
материалы представлены исключительно в ознакомительных целях. Подделка проездных билетов является уголовным преступлением и преследуется по закону.
Описание носителя карты Подорожник и подбор ключей шифрования
Как и московский товарищ, Подорожник базируется на смарт-картах типа
MIFARE. Такие карты используются во многих городах мира как для контроля оплаты проезда, так и в других целях, более подробно с применимостью данных карт можно ознакомиться
тут.
В качестве стандарта носителя Подорожника выбран
MIFARE Plus 4K, работающий в режиме совместимости с MIFARE Classic.
Данный стандарт является усовершенствованной версией MIFARE Classic: алгоритм шифрования был изменён на AES, что позволило закрыть известные на момент выхода уязвимости. Первые MIFARE Plus появились в 2009 году и до конца 2015 года в публичном доступе не было информации о каких-либо уязвимостях в данных носителях.
В октябре 2015 года вышла в свет работа "
Ciphertext-only Cryptanalysis on Hardened Mifare Classic Cards", описывающая атаку на карты MIFARE, работающие в режиме совместимости с Mifare Classic. Именно работа Подорожника в режиме совместимости позволила получить дальнейший доступ к карте. Отдельно хочу отметить, что никаких приложений (мобильных или десктопных) позволяющих взаимодействовать с Подорожником не выпускалось, поэтому вариант извлечения ключей используя реверс-инжиниринг (как в случае с Тройкой) автоматически отпал.
Память MIFARE Plus 4K разбита на 40 секторов: первые 32 сектора содержат 64 байта информации, последние 8 — 256 байт, что в сумме и даёт 4096 байт, которые указаны в названии.
Для доступа к каждому сектору используется два ключа, KeyA и KeyB — они никак не зависят друг от друга и применяются для чтения/записи соответственно.
В апреле 2016 года на Github появился репозиторий
aczid/crypto1_bs, содержащий реализацию атаки описанную в научной статье. Я не буду подробно останавливаться на процессе компиляции и запуска скрипта, лишь скажу, что для атаки достаточно использовать любой libnfc-ридер, например, известный в узких кругах
ACR122U.
Таким образом были получены ключи A и B от всех 40 секторов карты Подорожник.
Анализ памяти карты
После получения ключей доступа к секторам, стало возможно чтение и запись любых данных на карту. После снятия первых дампов сразу бросилось в глаза, что большинство секторов (1-3, 6, 7, 13-39) забиты нулями и никак не используются: для чего в таком случае используется карта на 4 Кб (а не на 2, например) для меня осталось загадкой. Более того, после нескольких поездок было обнаружено, что данные меняются только в секторах 4, 5 и 9. Так же сразу стало очевидно, что сектор 9 содержит в себе только данные о числе поездок за текущий месяц: значения в некоторых блоках памяти только инкрементируются и соответствуют этому показателю.
Самое же интересное происходит в секторах 4 и 5 — привожу их значения до и после одной из поездок:
+Sector: 4 +Sector: 4
F02300000FDCFFFFF023000000FF00FF E01500001FEAFFFFE015000000FF00FF
F02300000FDCFFFFF023000000FF00FF E01500001FEAFFFFE015000000FF00FF
FC00D11439014D04204E0001371E8066 FC00D11439014D04204E0001371E8066
E56AC127DD4548778B0019FC84A3784B E56AC127DD4548778B0019FC84A3784B
+Sector: 5 +Sector: 5
94293901C532100E0000000000009E39 102B3901851E100E000000000000AF9B
030094293900B96D0690000000000000 0400102B3900386D9A9A000000000000
030094293900B96D0690000000000000 0400102B3900386D9A9A000000000000
77DABC9825E17F0788009764FEC3154A 77DABC9825E17F0788009764FEC3154A
Легко заметить, что первый и второй блоки в секторе 4 всегда совпадают, точно так же ведут себя блоки 2 и 3 в пятом секторе. Экспериментируя с различными балансами, валидаторами в метро и наземном транспорте и интервалами между поездками удалось выяснить следующее:
- Первые 2 байта первого (или второго) блока четвёртого сектора хранят в себе информацию о балансе электронного кошелька карты в виде целочисленного числа, последние 2 разряда которого содержат информацию о копейках.
- Первые 4 байта первого блока пятого сектора хранят количество минут, прошедших с 1 января 2010 года. Таким образом, информация о последней поездке хранится на карте с точностью до минуты.
- Следом за минутами, два байта выделено для идентификатора валидатора: эти идентификаторы отличаются даже в пределах одной станции метро и получить одинаковое значение можно лишь пройдя через тот же турникет.
- Первый байт второго (или третьего) блока пятого сектора хранит в себе информацию о кол-ве поездок в текущем месяце, аналогично той, что записана в девятом секторе.
Кроме этого, в 5-м секторе находится
имитовставка: результат хеш-функции от каких-то хранящихся на данных карте. Возможное её расположение — последние 2 байта первого блока и, возможно, середина второго (третьего) блока. Имитовставка используется в качестве дополнительной защиты и не позволяет менять баланс (и любые другие критичные для оплаты данные) на произвольные значение, тем самым сильно уменьшая возможности для атаки. Тем не менее, имитовставка не является преградой, если речь идёт об атаке повторного воспроизведения.
Атака повторного воспроизведения
Атака повторного воспроизведения (replay) — атака на систему аутентификации путём записи и последующего воспроизведения ранее посланных корректных сообщений или их частей.
Данный тип атаки можно применить как раз в этом случае: так как возможность генерировать имитовставку под нужные данные отсутствует (по причине неизвестного алгоритма её формирования), остаётся лишь вариант полного сохранения состояния карты после пополнения баланса и возврат к нему при необходимости.
Тестирование атаки производилось по следующим схемам:
- Пополнение баланса, сохранение дампа, трата доступных средств, восстановление дампа и попытка пополнить баланс через автомат, результат — мгновенная блокировка карты.
- Пополнение баланса, сохранение дампа, трата доступных средств, восстановление дампа и последующий проход в метро, результат — успешный проход в метро, блокировка карты спустя 2 часа после прохода.
- Пополнение баланса, сохранение дампа, трата доступных средств, восстановление дампа и последующие поездки только в наземном транспорте, результат — никаких блокировок, удалось повторить несколько раз.
- Пополнение баланса, сохранение дампа, трата доступных средств, восстановление дампа, поездка в наземном транспорте, поездка в метро, результат — успешный проход в метро, блокировка карты спустя 2 часа после прохода.
После блокировки карты в метро, её все ещё можно использовать в наземных видах транспорта довольно продолжительное время: внесённый в стоп-лист Подорожник работал ещё минимум 2 недели, после чего тестирование было прекращено.
Таким образом, данная атака позволяет бесплатно и без каких-либо ограничений пользоваться любыми наземными видами транспорта: карта Подорожник принимается к оплате в автобусах, троллейбусах, трамваях и маршрутные такси.
С метрополитеном ситуация не такая: турникеты синхронизируются очень оперативно и любые попытки обойти защиту заканчиваются блокировкой карты в кратчайшие сроки. Пассажиропоток петербургского метрополитена составляет около 5 млн человек в день, поэтому меня приятно удивил тот факт, что несмотря на большую нагрузку, система защиты в метро работает без нареканий.
Мобильное приложение Plantain
Для ускорения процесса тестирования, я написал простое приложение, способное считывать информацию с Подорожника, а так же сохранять и восстанавливать его состояние.
Для работы потребуется телефон с ОС Android 4.2+ с NFC-модулем. Работа приложения протестирована на Yotaphone 2 и планшете Google Nexus 7.
Я занимаюсь веб-разработкой и до этого не имел дела с разработкой под Android, поэтому код может быть написан не по гайдлайнам и с использованием bad practices.
Ссылка на Github:
github.com/bafoed/plantain
Готовую .apk-версию можно скачать на странице релизов:
github.com/bafoed/plantain/releases
Заключение
В заключении хочу сказать, что описанные в данной статье уязвимости являются следствием ошибок, допущенных ещё при создании первых версий Подорожника. Используемые носители MIFARE Plus могут работать в режиме с использованием криптографически безопасного AES, и с какой целью на картах включена совместимость со старым, уязвимым стандартом, сказать сложно. Для исправления уязвимости необходимо значительно участить сбор и анализ данных на валидаторах наземного транспорта (по тому же принципу, как это сделано в метрополитене), усовершенствовать методы хранения данных на памяти карты, или идти в ногу со временем и обновлять аппаратные и программные составляющие компоненты под современные реалии информационной безопасности.
комментарии (133)