H Уязвимость карты Подорожник: бесплатные поездки в наземном транспорте Санкт-Петербурга в черновиках

H Уязвимость карты Подорожник: бесплатные поездки в наземном транспорте Санкт-Петербурга в черновиках

Почти год назад на Хабрахабре появилась статья «Исследование защищенности карты Тройка», в которой было подробно описано устройство проездных билетов и векторы атаки на систему оплаты общественного транспорта в Москве. Ещё тогда, вдохновившись прочитанным, мне захотелось попробовать применить описанные в статье приёмы к петербургскому аналогу Тройки — карте Подорожник, которая используется для оплаты поездок в общественном транспорте города. Как и в оригинальной статье, спешу предупредить читателей: материалы представлены исключительно в ознакомительных целях. Подделка проездных билетов является уголовным преступлением и преследуется по закону.

Описание носителя карты Подорожник и подбор ключей шифрования

Как и московский товарищ, Подорожник базируется на смарт-картах типа 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 — привожу их значения до и после одной из поездок:

Легко заметить, что первый и второй блоки в секторе 4 всегда совпадают, точно так же ведут себя блоки 2 и 3 в пятом секторе. Экспериментируя с различными балансами, валидаторами в метро и наземном транспорте и интервалами между поездками удалось выяснить следующее:

  • Первые 2 байта первого (или второго) блока четвёртого сектора хранят в себе информацию о балансе электронного кошелька карты в виде целочисленного числа, последние 2 разряда которого содержат информацию о копейках.
  • Первые 4 байта первого блока пятого сектора хранят количество минут, прошедших с 1 января 2010 года. Таким образом, информация о последней поездке хранится на карте с точностью до минуты.
  • Следом за минутами, два байта выделено для идентификатора валидатора: эти идентификаторы отличаются даже в пределах одной станции метро и получить одинаковое значение можно лишь пройдя через тот же турникет.
  • Первый байт второго (или третьего) блока пятого сектора хранит в себе информацию о кол-ве поездок в текущем месяце, аналогично той, что записана в девятом секторе.

Атака повторного воспроизведения

Атака повторного воспроизведения (replay) — атака на систему аутентификации путём записи и последующего воспроизведения ранее посланных корректных сообщений или их частей. Данный тип атаки можно применить как раз в этом случае: так как возможность генерировать имитовставку под нужные данные отсутствует (по причине неизвестного алгоритма её формирования), остаётся лишь вариант полного сохранения состояния карты после пополнения баланса и возврат к нему при необходимости.

Тестирование атаки производилось по следующим схемам:

  1. Пополнение баланса, сохранение дампа, трата доступных средств, восстановление дампа и попытка пополнить баланс через автомат, результат — мгновенная блокировка карты .
  2. Пополнение баланса, сохранение дампа, трата доступных средств, восстановление дампа и последующий проход в метро, результат — успешный проход в метро, блокировка карты спустя 2 часа после прохода .
  3. Пополнение баланса, сохранение дампа, трата доступных средств, восстановление дампа и последующие поездки только в наземном транспорте, результат — никаких блокировок, удалось повторить несколько раз .
  4. Пополнение баланса, сохранение дампа, трата доступных средств, восстановление дампа, поездка в наземном транспорте, поездка в метро, результат — успешный проход в метро, блокировка карты спустя 2 часа после прохода .

Таким образом, данная атака позволяет бесплатно и без каких-либо ограничений пользоваться любыми наземными видами транспорта: карта Подорожник принимается к оплате в автобусах, троллейбусах, трамваях и маршрутных такси.

С метрополитеном ситуация не такая: турникеты синхронизируются очень оперативно и любые попытки обойти защиту заканчиваются блокировкой карты в кратчайшие сроки. Пассажиропоток петербургского метрополитена составляет около 5 млн человек в день, поэтому меня приятно удивил тот факт, что несмотря на большую нагрузку, система защиты в метро работает без нареканий.

Мобильное приложение Plantain

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

Для работы потребуется телефон с ОС Android 4.2+ с NFC-модулем производства NXP. Работа приложения протестирована на Yotaphone 2 и планшете Google Nexus 7.

Я занимаюсь веб-разработкой и до этого не имел дела с разработкой под Android, поэтому код может быть написан не по гайдлайнам и с использованием bad practices.

📎📎📎📎📎📎📎📎📎📎