Большая ретроспектива участия RBK.money в The Standoff 2020
…или как хакеры ломали наш опенсорс платежный процессинг в кибергороде.
Привет! Мы тут недавно с процессингом 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 дня больше атак, чем к нам штатно приходит за полгода.
Мы многому научились, и самое главное — увидели, что наш продукт, который мы пишем для себя и для вас, пользуется популярностью у участников кибергорода, для нашего ИТ это было сильной мотивацией — ведь приятно, когда результатом твоего труда пользуются люди, пусть в данном случае и с весьма специфическими целями.
Нам очень понравилось и хочется ЕЩË.
В следующем Стендоффе ждите нас с еще более интересными схемами, большим количеством платежных функций и новыми векторами атак!