…или как хакеры ломали наш опенсорс платежный процессинг в кибергороде.

Привет! Мы тут недавно с процессингом RBK.money приняли активное участие в киберполигоне The Standoff — это когда делают виртуальную модель целого мегаполиса со всей его инфраструктурой, энергостанциями, магазинами и прочими важными элементами. А потом пускают в этот цифровой двойник города команды blue team (6 команд в этом году) и red team (29 команд в этом году соответственно), первая защищает всю эту инфраструктуру, вторая же активно пытается что-то сломать.


из к/ф “Бегущий по лезвию 2049”

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

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

Внедрялись в кибергород мы в ощутимой спешке: это один из первых наших деплойментов в Kubernetes (до этого мы все разворачивали Salt-стейтами), и нам пришлось использовать новые подходы по инсталляции. И последствия от этой спешки не заставили себя долго ждать.

Подсказки хакерам




Ещё до раскатки процессинга на кибергород мы намеренно оставили там два довольно слабых места.

Первое — уязвимость, связанная с методами токенизации карт. Эти методы были подвержены уязвимости в виде replay-атак, то есть карту можно было успешно токенизировать в каком-то одном магазине, а потом с этим токеном прийти в другой и переиспользовать его там. Мы робко надеялись, что уязвимость найдут, но увы.

Второе — простая учетка главного мерчанта. Мы создали всего одного мерчанта-олигарха, это было юридическое лицо, которое владело интернет-магазинами в кибергороде. И у этого толстосума были довольно простые учетные данные, то есть пароль вида Parolec0 в принципе можно было бы и подобрать. Но тоже не взлетело.

Зато взошли наши собственные косяки.

Поспешишь — не всё защитишь




Внимательный читатель из пункта про главного мерчанта сделает вывод — погодите-ка, это же у вас один-единственный олигарх, которому принадлежат все интернет-магазины, достаточно взломать один такой интернет-магазин, и можно получить доступ к остальным. Ну да, вот так в спешке не продумали этот момент..

И на самом деле, можно было после взлома этого мерчанта достать его API-ключ для нашего процессинга и этим процессингом полноценно управлять. Собственно, это и случилось — атакующие взломали стороннее решение, интернет-магазин развлечений города, достали оттуда API-ключ нашего мерчанта, пришли с ним в наш процессинг и вызвали метод, который позволяет включать-выключать свой интернет-магазин. И так как одно юрлицо владело всеми торговыми точками по всему городу, они все и отключились.

В принципе, это правильно, если ты здоровенный жадный олигарх, который захапал себе вообще всё — страдай. Мы сделали выводы и решили оперативно раскулачить толстосума, создав ещё 5 самостоятельных юридических лиц, и для каждого отдельные пары “логин-пароль” и API-ключ. Думаю, в следующих подобных соревнованиях постараемся сделать ситуацию еще более приближенной к реальности в бизнесовой ее части.

А ещё “наприлетало” из-за особенностей кубера.

В Kubernetes основное хранилище о состоянии кластера — ETCD, полезная распределенная система, на которой можно строить весьма и весьма надежные штуки. Но она слишком критична к latency жестких дисков.

Как я писал, мы разворачивали процессинг в виртуальной среде кибергорода. На соседние с нами объекты шли довольно активные атаки, и однажды к нам на датастор кубера передвинули один из таких “шумных” объектов, инфраструктуру одного из участников, которую ломали долго и упорно. И хотя де-факто мы в этом случае не были мишенью и в тот момент никто не ломал именно процессинг, он продолжал работать штатно, но сам кластер начал дико тормозить, харды просто не справлялись (успели заметить что вывод команды ls -l занимал порядка 19 секунд). Получилось, что вышел своеобразный DoS, и в одну ночь мы отдавали на все запросы наших стандартных котиков.



После этой ситуации организаторы The Standoff передвинули нас на другие диски, то есть погасили одну виртуальную машину и включили еще одну, в другой локации. После чего наша распределенная СУБД радостно словила split-brain, половина нод содержали одну информацию, половина — другую, и особо не могли с собой договориться. На бою мы, конечно, серьезнее бы заморочились с миграцией и не допустили подобного. А в тестовой среде куда проще было просто грохнуть все имеющееся и инсталлировать заново, что мы и сделали, потратив, кстати, 2 часа. Почему я это выделяю — потому что мы развернули полноценный рабочий процессинг со всеми составляющими за два часа, и такое с нашим процессингом вы можете проделать на бою в своей компании. Классические процессинги обычно разворачивают в компаниях месяца 3.

Так вот, про split-brain, это все спешка. Мы в запаре просто на одной из нод под корень снесли /tmp. Кто ж знал, что модуль CSI LVM, который раздает локальные тома с железа в поды, скрыто (!) монтирует персистентный том кубера в /tmp. Таким образом получилось, что мы своими собственными руками снесли данные под ногами СУБД, которые на ней крутились. Причем, несмотря на то, что мы снесли хранилище для части нод в кластерах баз, у нас все продолжало работать до первого перезапуска виртуальной машины, который случился, когда нас начали переносить на новые сторы.

Blue-team медленно выключает свою защиту…




В один из дней команды blue-team решили выключить внешние защиты (firewall и прочее). То есть первые пару дней хакеры пытались ломать системы с включенной защитой такого рода, а потом — без. У нас также стоял сторонний WAF, который в ингрессе с нжинксом в виде модуля подгружался и защищал наш трафик.

И вот настал этот день, мы пошли выключать WAF и поняли, что он и так уже отключен. Два дня назад. Потому что мы молодцы и в спешке (да, да), настраивали ingress kubernetes, на котором был экземпляр WAF. И всё бы хорошо, но WAF банально не достучался до управляющего сервера, не смог с него скачать файл лицензии, пожал плечами и просто выключился от греха. И получается, что мы все эти два дня “Ломаем с включенной защитой” сидели, собственно, без этой защиты.

Но всё равно нас не сломали.

Ещё одно подкрепление тезиса, что спешить вредно (вдруг вам мало предыдущих) — ситуация с нашим антифродом. Я описывал его в предыдущих постах блога, там волшебная коробка с набором правил. Антифрод защищает от перебора банковских карт, попыток оплатить в одну точку из разных локаций / IP / email и прочих недружественных действий. Мы сказали команде защиты, что сами вдумчиво настроим все эти правила.

И мы это сделали — мы тщательно настроили все правила для антифрода. На нашем боевом сервере RBK.money вместо инсталляции для The Standoff. Банально перепутали урлы UI в адресной строке браузера. То есть антифрод на это время представлял собой коробку с молчаливой загадочной пустотой.

Это и стало одним из успешных векторов для редов:
например, они до этого взломали сторонний интернет-банк, стырив PAN-код карты (сами цифры, Primary Account Number), имя держателя карты и подобрав дату действия. После этого уже в нашем процессинге по этому PAN стали перебирать CVV. И все было бы хорошо, после 3 попытки перебора карты были бы заблокированы нашим антифродом. Если бы… см выше.

А вообще подобных смешных историй было много. В какой-то момент у нас перестали резолвиться сервисы и перестало синхронизироваться время на нодах, причем как-то рандомно, с части хостов.

Конечно, первым делом грешили на мисконфиг, непонятную работу кластера.

С DNS проблему быстро решили выносом CoreDNS подов прямо на ноды, где этот трафик не фаерволился, а с NTP нам повезло — по счастью, большого clock skew мы не поймали, а при создании кластера ноды еще успели синхронизироваться.

Оказалось — в какой-то момент на уровне фаервола были отключены исходящие NTP- и DNS-запросы для части нод. Видать, кто-то слишком сильно закрутил гайки с фильтрацией.

Другие атаки




Атаки на другие соседние объекты кибергорода также временами проходили успешно, включая те, что, как и мы, были в финансовой системе кибергорода.

Хорошо, что мы не перепутали урлы алертов над эластиком и в мониторинге, и видели их достаточно точно и достаточно быстро.

Для примера, как в случае со взломом нашего олигарха и уведённым API-ключом. Взломали его в 22.17 МСК. В 22.22 мы на своей стороне заметили это и сразу отрепортили команде защитников и организаторам. Заметили, кстати, благодаря кривому использованию API — хакеры передали в первом запросе странный заголовок content type, вызывали редкий метод нашего API, еще кое-какие нюансы — вот и был повод сработать алерту.

Когда система работает штатно и автоматически, это все редко совпадает одновременно. А вот если происходит подобное, значит, с API кто-то играется именно руками. Вот алерт и сработал.
Если говорить не о кибергороде, а о реальных ситуациях такого рода, то тут все происходит еще быстрее, в таких случаях система автоматически блокирует действия мерчанта, чтобы у него со счета ничего не вывели и в принципе никак не навредили работе и бизнесу, поднимает панику и подключает уже живых сотрудников

На будущее


Формат взлома кибергорода — это, без шуток, будущее информационной безопасности. Мы обязательно пойдем сюда снова, учтем все ошибки и продумаем инфраструктуру и бизнес-схемы так, чтобы они были максимально приближены к реальности. В идеале вообще хочется, чтобы к таким же выводам пришли люди из ЦБ или Госуслуг — протестить свою инфраструктуру в бою, предоставить возможность найти уязвимости и стать еще лучше и надежнее для пользователей и бизнеса.

И это на самом деле было очень классно и весело. Фактически мы получили большой набор Chaos Monkey-кейсов, которые не факт что стали бы воспроизводить на продакшене, мы протестировали процессинг на атаки, получив за 2 дня больше атак, чем к нам штатно приходит за полгода.

Мы многому научились, и самое главное — увидели, что наш продукт, который мы пишем для себя и для вас, пользуется популярностью у участников кибергорода, для нашего ИТ это было сильной мотивацией — ведь приятно, когда результатом твоего труда пользуются люди, пусть в данном случае и с весьма специфическими целями.

Нам очень понравилось и хочется ЕЩE.

В следующем Стендоффе ждите нас с еще более интересными схемами, большим количеством платежных функций и новыми векторами атак!