- PVSM.RU - https://www.pvsm.ru -
Автор: cuamckuu [1]
Извлечение содержимого карты и работа с EMV-командами может быть интересна не только в исследовательских целях. Существует несколько видов атак на бесконтактные банковские карты, про реализацию которых будет рассказано под катом.
В этом году я попал на стажировку Summer of Hack 2019 в Digital Security и поработал над темой исследования бесконтактных EMV-карт. В ходе стажировки получилось лучше узнать о том, как работают банковские карты, и создать новую утилиту для работы с бесконтактными картами. С демонстрацией режима считывания данных можно познакомиться здесь [2].
Карта и терминал общаются, используя стандарт EMV (Europay + MasterCard + VISA), который разрабатывался для повышения безопасности платежей. В связи с этим, существует не так много векторов атак на бесконтактные карты. В статье речь пойдёт о следующих:
Такие атаки возможны при взаимодействии с картой по EMV-стандарту. Многие карты позволяют без проблем считать приватную информацию пользователя, в частности PAN, срок действия и имя держателя. Считанных данных хватает для привязки карты в некоторых онлайн-магазинах, например, Amazon. А полученные приватные данные можно использовать для более персонализированного фишинга или при рассылке спама.
Похожим способом реализуется DoS-атака. Вызов нужных EMV-команд позволяет переполнить внутренний счётчик транзакций или имитировать неправильный ввод PIN-кода, что приводит к блокировке карты.
Перед началом разработки было решено изучить существующие решения. В частности, были рассмотрены: RFIDIOt/ChAP.py [3], Jaccal [4], nfcmillionaire [5], PoC с конференций [6], “Ruby” script [7], Android apps/libs [8].
Большинство из рассмотренных программ пытаются имитировать работу POS-терминала и используют словари с идентификаторами поддерживаемых карт, поэтому часто такие решения будут работать только с Visa и MasterCard.
Другой проблемой является считывание малой части данных вместо снятия полного дампа. Почти все программы пытаются разобрать как можно больше EMV на лету и делают ошибки при разборе.
Если какая-то из проблем отсутствует или не так сильно выражена, то скорее всего речь идёт о приложении/библиотеке для Android, и вам потребуется телефон с NFC-ридером, который пока есть не у всех.
Описанные проблемы можно решить, для этого следует:
На Хабре уже есть статьи, подробно описывающие процесс взаимодействия карты и терминала (раз [9], два [10], три [11]), поэтому постараюсь не повторяться и сосредоточиться на практической части.
Для общения с картой будем использовать ридер PN532 из-за приятной цены и библиотеку libnfc. Плавно переходим к делу. Данные на карте организованы следующим образом:
Окружения -> Приложения -> Файлы -> Записи.
Цель считывания – получить данные всех записей, для этого нужно пройти полную цепочку, причём выбор окружения и приложения происходит только один раз в начале общения.
Тот же процесс в терминах EMV-команд:
Рассмотрим пример формирования одной из команд. Первая команда для выбора бесконтактного окружения всегда одинаковая и выглядит следующим образом:
byte_t const command[] = {
0x40, 0x01, // Pn532 InDataExchange
0x00, 0xA4, // SELECT ppse
0x04, 0x00, // P1:By name, P2:_
0x0e, // Lc: Data length
0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, // Data string:
0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, // 2PAY.SYS.DDF01 (PPSE)
0x00 // Le
};
Пример ответа: 6F 23 84 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 11 BF 0C 0E 61 0C 4F 07 A0 00 00 00 03 10 10 87 01 01 90 00
Для вызова следующей команды нам потребуется разобрать ответ предыдущей команды.
Нас интересует идентификатор приложения AID. Запоминаем его и формируем новый SELECT запрос, но на этот раз передаём команде SELECT полученный AID, а не PPSE, как в первой команде.
Пример: 00 A4 04 00 07 A0 00 00 00 03 10 10 00
Как было сказано ранее, важно получать AID динамически, а не использовать подготовленный словарь, тогда ваше приложение с большой вероятностью сможет считывать разные виды карт, например, карты МИР.
После того, как приложение выбрано, мы можем читать необходимые записи, используя команду READ RECORD и передавая в качестве параметров номер файла и номер записи.
Пример формирования команды: (подробнее об этом можно почитать в стандарте. EMV Book1. 11.2 READ RECORD)
byte_t const sfi_param = (sfi << 3) | (1 << 2);
byte_t const command[] = {
0x40, 0x01, // Pn532 InDataExchange
0x00, 0xB2, // READ RECORD
record_number, sfi_param, // P1:record_number and P2:SFI
0x00 // Le
};
Пример вызова: 00 B2 02 14 00
Заметим, что под номер файла отводится не полный байт, соответственно, всего файлов может быть 31 (2^5 — 1), а записей 255. Файлы с 1-го по 10-й отводятся для хранения внутренних данных, а оставшиеся отводятся под хранение лога транзакций, если карта поддерживает логирование.
Теперь используя два вложенных цикла, мы можем получить данные всех записей карты, вызывая для каждой пары команду READ RECORD. Процесс перебора можно существенно ускорить, если обращать внимание на возвращаемый картой status word (последние два байта ответа). Статус может сказать нам о том, что файла не существует (SW = 0x6A82) или о том, что дальше в этом файле нет записей (SW = 0x6A83).
На практике выяснилось, что имеет смысл рассматривать только случай несуществующего файла, так как иногда встречаются карты, которые некорректно используют статус код для отсутствующих записей. После чтения данных можно отправить их в один из онлайн-парсеров, мне понравился этот [12].
Фрагмент данных, извлечённых из записей карты:
Считанных данных хватит для привязки карты в некоторых онлайн-магазинах (в основном, в зарубежных), также полученную информацию можно использовать для более персонализированной атаки с применением социальной инженерии.
Переходим к следующему виду атаки. Для DoS-a существует, как минимум, 2 способа реализации.
Для реализации медленного способа (атака потребует около 4 минут) необходимо переполнить внутренний счётчик транзакций карты (ATC). Для этого требуется вызвать:
Рассмотрим шаги подробнее. Выбор бесконтактного окружения и приложения аналогичен пункту с извлечением данных, единственным отличием является то, что на этот раз нам потребуется обработать ответ команды SELECT APPLICATION.
Нас интересует поле PDOL, так как оно понадобится для последующего вызова команды GET PROCESSING OPTIONS, которая и будет увеличивать счётчик транзакций при каждом вызове.
В PDOL-е карта просит от нас информацию о терминале и платеже.
В примере выше карта просит у нас:
Поскольку мы реализуем DoS, а не реальный платёж, мы можем не заботиться о правильности значений и просто использовать заранее подготовленные значения, которые примет карта. Подробнее о требуемых значениях можно почитать в стандарте. (EMV Book 3. Annex A Data Elements Dictionary).
Для удобства практического использования привожу таблицу:
Тег (Hex) | Описание | Валидное значение (Hex) |
9F59 | Terminal Transaction Information | C8 80 00 |
9F5A | Terminal Transaction Type | 00 |
9F58 | Merchant Type Indicator | 01 |
9F66 | Terminal Transaction Qualifiers | 79 00 40 80 |
9F02 | Amount (authorized) | 00 00 00 10 00 00 |
9F03 | Amount (Other) | 00 00 00 00 00 00 |
9F1A | Terminal Country Code | 01 24 |
5F2A | Transaction Currency Code | 01 24 |
95 | Terminal Verification Results | 00 00 00 00 00 |
9A | Transaction Date | 19 01 01 |
9C | Transaction Type | 00 |
9F37 | Unpredictable Number | 82 3D DE 7A |
Сформировав данные, запрашиваемые картой, мы готовы к вызову GPO.
Пример: 80 A8 00 00 12 83 10 79 00 40 80 00 00 00 10 00 00 82 3D DE 7A 01 24 00
Ответ: 77 4F 82 02 20 00 94 0C 10 02 03 00 18 01 01 00 10 04 04 00 57 13 42 76 55 00 66 83 25 13 D2 00 52 01 14 89 36 20 00 00 1F 5F 20 02 20 2F 9F 10 07 06 01 11 03 80 20 00 9F 6C 02 30 00 9F 26 08 33 33 89 D5 70 A3 DF 37 9F 27 01 00 9F 36 02 02 48 90 00
Повторяем вызов GPO 65 536 раз, и карта блокируется. Можно уменьшить количество требуемых вызовов, если предварительно считать текущее значение ATC с помощью GET DATA.
Быстрый способ намного удобнее (и опаснее), так как потребует около 2 секунд для блокировки карты, поэтому подробный разбор деталей реализации останется за кадром.
Метод похож на предыдущий, но на этот раз потребуется понизить счётчик попыток ввода PIN-кода, вместо повышения счётчика транзакций. Значение PIN Try Counter также можно получить через GET DATA, но в данном случае существенного прироста по скорости не будет.
Требуемые операции:
В ходе стажировки получилось создать новый инструмент для работы с бесконтактными банковскими картами и решить несколько проблем присутствующих в существующих решениях, а использование дешёвого ридера значительно понижает стоимость исследовательского набора и может поспособствовать привлечению новых людей к исследованию безопасности бесконтактных банковских карт. Исходный код программы доступен на Github [13].
Автор: forkyforky
Источник [14]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/informatsionnaya-bezopasnost/332345
Ссылки в тексте:
[1] cuamckuu: https://habr.com/ru/users/cuamckuu/
[2] познакомиться здесь: https://asciinema.org/a/ZaCFZU2x9EN5gCAEvogPn4YGm
[3] RFIDIOt/ChAP.py: https://github.com/AdamLaurie/RFIDIOt/blob/master/ChAP.py
[4] Jaccal: http://jaccal.sourceforge.net/
[5] nfcmillionaire: https://github.com/laane/nfcmillionaire
[6] PoC с конференций: https://gist.github.com/bluec0re/7b32da7ec317b1f1c812
[7] “Ruby” script: https://github.com/ansjdnakjdnajkd/emv
[8] Android apps/libs: https://github.com/pro100svitlo/Credit-Card-NFC-Reader
[9] раз: https://habr.com/ru/post/109361/
[10] два: https://habr.com/ru/post/422551/
[11] три: https://habr.com/ru/company/dsec/blog/421543/
[12] этот: http://www.emvlab.org/tlvutils/
[13] доступен на Github: https://github.com/cuamckuu/nfc-frog
[14] Источник: https://habr.com/ru/post/468937/?utm_source=habrahabr&utm_medium=rss&utm_campaign=468937
Нажмите здесь для печати.