Payment Village на PHDays 11: как проверяли на прочность онлайн-банк

Payment Village на PHDays 11: как проверяли на прочность онлайн-банк

Всем привет! В нашем блоге мы уже рассказывали о том, что на форуме  Positive Hack Days 11  работала специальная зона Payment Village, где любой желающий мог поискать уязвимые места в онлайн-банке, банкоматах (если вдруг пропустили, читайте подробный райтап) и POS-терминалах. Конкурс по обнаружению уязвимостей в онлайн-банке не новый, однако в последние годы его немного потеснили активности по этичному хакингу других финансовых систем. В 2022 году мы решили исправить эту несправедливость и создали новую банковскую платформу, применив накопленный за все это время опыт. Участникам предлагалось найти типовые банковские уязвимости и зарепортить их нам. По сценарию конкурса можно было играть либо за «белых шляп» (участвовать в программе bug bounty онлайн-банка), либо за «черных шляп» (стараться украсть из банка как можно больше денег).

В первую очередь мы оценивали критичность каждого найденного бага, затем подсчитывали общее количество уязвимостей, которое участник нашел во время исследования банковской системы. Награда в 50 тысяч рублей по традиции присуждалась тому, кто обнаружил самые опасные бреши, — в этом году победителем стал catferq. Он отыскал наибольшее число заложенных нами уязвимостей, среди которых были два критических бага, а также один баг, о наличии которого не подозревали даже мы :). Кроме catferq были награждены и другие участники, обнаружившие уязвимости с менее высоким уровнем риска: hundred303, null1337undefined, kab5fa2hs, HackathonDev и c0rv4x. Благодарим всех, кто принял участие в нашем конкурсе: было очень интересно читать ваши репорты и отзывы по улучшению активности.

Немного про онлайн-банк

В этом году мы решили не использовать предыдущие наработки, а создать для конкурса новый сервис с нуля. За эту задачку со звездочкой взялся один из самых молодых специалистов нашей команды по исследованию безопасности банковских систем — он работал над этим проектом под наставничеством более опытных коллег. Наш онлайн-банк состоял из фронтенд- и бэкенд-частей, а также автоматизированной банковской системы (АБС). Вместе с базой данных (postgres) и хранилищем куки (redis) он был поднят в нескольких связанных друг с другом контейнерах. Кстати, банк до сих пор  доступен  — можете поизучать его прямо сейчас.

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

Чтобы обнаружить уязвимости, которые мы заложили в онлайн-банк, участникам требовалось проявить смекалку и применить все свои пентестерские навыки.

Недоработки авторизации и парольной политики онлайн-банка

Начнем разбор заданий с входной точки для любого злоумышленника — формы входа в личный кабинет.

Брутфорс формы входа

При регистрации внимательные участники могли заметить:

  • слабую парольную политику онлайн-банка;

  • IP-адрес атакующего, пробовавшего взломать аккаунты методом перебора паролей, не блокировался.

Рассмотрим этот кейс на примере одного из аккаунтов и попробуем подобрать пароль к учетной записи User1234. Несмотря на большое число попыток ввода неверного пароля, мы каждый раз получаем сообщение invalid username or password:

А теперь попробуем ввести верный пароль:

Как видите, ответ изменился: система на пять минут заблокировала вход в аккаунт. На самом деле блокировка произошла во время одной из попыток ввода неверного пароля. Помимо того, что система не запрещает перебирать данные аккаунтов (хотя и пытается скрыть это под сообщением invalid username or password), у участников была еще возможность подобрать пароли от известных им аккаунтов по словарям. Например, в футере главной страницы онлайн-банка были указаны контакты администраторов (имя пользователя и адрес электронной почты), с которыми, по легенде конкурса, могли связаться участники. Как вариант, можно было попробовать перебрать пароль одного из администраторов по словарю rockyou.

Результаты задания на PHDays 11: ни один из участников не смог обнаружить данную уязвимость.

Брутфорс CVV

Отсутствие в системе защиты от перебора пароля открывало для участников еще одну возможность для атаки — брутфорс CVV на банковских картах. Чтобы получить PAN карт, содержащихся в системе, участники могли воспользоваться уязвимостью с раскрытием карточных данных. Для ее эксплуатации необходимо было взять данные карты из системы и зайти с их помощью в онлайн-банк:

Получаем стандартный ответ о неверно введенных данных, запускаем перебор CVV и видим, как во время одного из запросов код ответа поменялся с 200 на 302. Остановимся детальнее на этом запросе-ответе.

Так система ведет себя только в одном из тысячи вариантов, что позволяет сделать вывод о том, что таким способом можно было подобрать CVV известных нам банковских карт.

Результаты задания на PHDays 11: ни один из участников не смог обнаружить эту уязвимость.

Брутфорс одноразового кода

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

Одноразовый код приходил участникам в Telegram-аккаунт, который они указывали при регистрации.

Верификация аккаунта и получение ОТР для входа:

Попробовав ввести неверный пароль, получаем от сервера ответ, что одноразовый пароль неверен.

Опытным путем выясняем, что OTP сменяется онлайн-банком один раз за тысячу попыток ввода.

И на этом этапе участникам конкурса стоило насторожиться: код состоял из четырех цифр. Это дает ненулевой шанс на угадывание требуемого для ввода одноразового кода. Отметим, что в реальных банковских системах установлены более строгие, хотя и не всегда достаточные с точки зрения ИБ ограничения на отправку одноразовых паролей.

Вспомним немного курс университетской (или школьной) математики. Каков шанс угадать четырехзначное число с десяти тысячи попыток при условии, что число меняется каждую тысячу попыток? Ответ: 1—(0,9)10  ~ 0,6513, где 0,9 — вероятность того, что за итерацию, пока будет доступно одно число, его не получится угадать.

Если нет желания углубляться в математику, придумывать свои скрипты на Python (или каком-то другом языке), а хочется сразу начать процесс перебора цифр, можно воспользоваться популярной утилитой для тестирования веб-уязвимостей Burp Suite. Изучив, как сервер отвечает в случае успешной проверки данных входа (логина, пароля или OTP), выставляем в параметрах Intruder регулярное выражение на ответ и запускаем атаку полным перебором.

Как видно на скриншоте, таким способом удалось угадать одноразовый код (не подглядывая в СМС с паролем!) с восьмого захода, или на 7317-й попытке.

Результаты задания на PHDays 11: двое участников обнаружили эту уязвимость и отправили нам отчет о ней. Интересно, что мы не заметили по логам, чтобы кто-то из участников в дальнейшем эксплуатировал ее для получения доступа к аккаунтам. По нашей задумке участники должны были провести брутфорс пароля одного из администраторов (его пароль угадывался по словарю перебора паролей Rockyou), а после попробовать попасть в аккаунт администратора, используя эту уязвимость.  

Недостатки бизнес-логики в OTP

Одним из этапов привязки Telegram-аккаунта для получения одноразовых паролей была его верификация. Участникам требовалось ввести специальный код, подтверждающий данные об аккаунте в системе. Любопытные хакеры начали бы размышлять так: «у нас есть два Telegram-аккаунта, если нам потребуется привязать второй вместо первого либо просто отвязать первый от конкретного личного кабинета, что с ним будет в системе? Теоретически его должны удалить». Но так ли это? Пробуем привязать его в другом личном кабинете. И — о чудо! — система не требует его верифицировать, а сразу добавляет его.

К чему может привести этот недостаток системы? Потенциальный злоумышленник может без верификации закрепить за своим личным кабинетом Telegram-аккаунт легитимного пользователя, тем самым лишив последнего возможности вновь привязать собственный аккаунт к своему личному кабинету для двухфакторной аутентификации. Кроме того, эта ошибка бизнес-логики в ходе  комплексной атаки  может привести к тому, что клиент банка не сможет воспользоваться двухфакторной аутентификацией со своего доверенного аккаунта. Также теперь злоумышленникам не нужно бороться с одноразовым кодом, а достаточно подобрать учетные данные жертвы. Вдобавок к этому данная уязвимость дает злоумышленникам возможность провести CSRF-атаку и привязать свой «потерявшийся» в системе аккаунт к профилю жертвы, заблокировав ей доступ к собственному личному кабинету. Все это делает пользовательский аккаунт уязвимым для атак злоумышленников.

Результаты задания на PHDays 11: только один участник прислал отчет об этой уязвимости.

Раскрытие маскированных данных по имени пользователя

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

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

Сделаем перевод одному из пользователей по имени:

  • 5572443375087227 — номер рублевой карты пользователя, который совершает перевод другому пользователю по его имени в системе;

  • 8531606207370870 — номер долларовой карты пользователя, который совершает перевод другому пользователю по его имени в системе.

Система успешно провела транзакцию:

Проверив, что делает фронтенд для получения этих данных, увидим, что в запросе на получение транзакций указывается параметр hidecard со значением true. В ответ сервер присылает «правильные» (с точки зрения ИБ) данные с маскированным номером карты.

Повторяем запрос, но вместо true в параметре hidecard выставляем значение false:

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

Результаты задания на PHDays 11: четыре участника направили отчеты об этой уязвимости.

Ошибки округления

Другая интересная ошибка, которую мы добавляем в наш конкурс уже не в первый раз, — это ошибка округления. Допустим, если курс доллара к рублю составляет 1:60, то за 60 рублей мы получим один доллар. А что, если мы попробуем перевести 36 копеек в центы? Сумма будет меньше стоимости одного цента, однако банк не может списать 36 копеек, начислив 0 центов. Он округлит сумму до 0,01 доллара. Таким образом за меньшую цену можно получить ту же сумму, но в валюте. При этом при переводе обратно можно вернуть 0,60 рубля. Сумма нехитрого заработка составит 60 − 36 = 24 копейки.

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

Номер рублевой карты пользователя — 7047169154995669, номер долларовой карты пользователя — 9384411725418749.

Курсы валют в банке:

Начальный баланс банковских карт:

Переведем, например, 100 рублей с рублевой карты на долларовую по текущему курсу.

Перевод прошел успешно. Обратим внимание на изменения в балансах карт:

Уже на данном этапе заметна уязвимость: при переводе 100 рублей по заявленному курсу в процессинге банка получилось следующее число: 1,257861… Однако центы — это сотые доллара, а не тысячные, из-за чего система округлила результат в большую сторону, как и требуется по правилам арифметики. Получилось — 1,26. Таким образом мы получили лишними целых 0,003 доллара.

Продемонстрируем серьезность данной уязвимости, попробовав на ней заработать. Для этого сделаем перевод в обратную сторону — на рублевую карту:

По актуальному курсу это будет 1,26 х 79,5 = 100,17 рубля! Изменившийся баланс карт подтверждает это:

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

Результаты задания на PHDays 11: данную уязвимость обнаружили пять участников. Более того, один из них предоставил скрипт, автоматизирующий процесс заработка денег при эксплуатации этой уязвимости. Благо разработчики системы ДБО, то есть мы, не мешали ему разными одноразовыми паролями и капчами. За счет автоматизации он украл скромные 500 рублей, чтобы наглядно показать нам возможность эксплуатации уязвимости. Хотя если бы это была реальная банковская система и настоящие злоумышленники, созданный скрипт помог похитить миллионы.

Оформление кредитов

Недостатки бизнес-логики при выдаче кредитов на одну карту

Как видно из ответа сервера, в онлайн-банке есть ограничение по количеству кредитов, оформленных на одну карту, — не более трех. Однако Logger Burp Suite показывает, что нам все-таки удалось получить четыре кредита на одну и ту же карту.

Первый запрос на оформление кредита:

Последний запрос на оформление кредита:

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

Результаты задания на PHDays 11: отчет об этой ошибке не отправил ни один из участников, хотя по логам системы ДБО мы увидели, что троим из них встретилась эта недоработка.

Insecure direct object reference (IDOR)

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

Доступные карты:

Операция по списанию денежных средств с карты другого пользователя:

Результаты задания на PHDays 11: репорты об этой уязвимости прислали два участника.

Обход ограничения по количеству кредитов

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

На скриншоте видно, что количество списываемых кредитов по карте достигло максимума. То же самое происходит и со второй картой.

Теперь попробуем обойти теоретический предел с помощью IDOR:

У нас получилось обойти лимит по количеству кредитов, указав банковскую карту другого пользователя (ее номер мы получили, проэксплуатировав уязвимость, связанную с раскрытием карточных данных по имени пользователя). Сообщение от сервера подтверждает, что открыто девять заявок на кредит, а не восемь. Ниже скриншот одной из последних заявок.

Результаты задания на PHDays 11: участники, которые обнаружили предыдущую уязвимость, к сожалению, не обратили внимание на описанное ограничение и не попробовали его обойти. Мы, со своей стороны, также не выявили тех, кто мог бы незаметно для нас использовать эту недоработку.

Отказ в обслуживании

Еще одной брешью в функционале кредитов было проведение DoS-атак (Denial of Service, отказ в обслуживании). Участникам был доступен кредитный калькулятор, который позволял рассчитывать количество и время платежей по выбранной программе. Рассмотрим, как можно было выявить DoS.

Сначала отправляем стандартный запрос с расчетом на ближайшее время:

Кажется, время ответа нормальное и ничего не предвещает беды. Но давайте поиграем с параметрами period и end_time. Сначала изменяем параметр end_time с 2023-го на 2070 год.

Как видите, прибавление годов увеличивает время ответа сервера. Теперь поменяем в параметре period 1 день на 1 час.

Время ответа сервера тоже кратно увеличилось — это позволяет сделать вывод, что в этом функционале есть DoS.

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

Результаты задания на PHDays 11: мы получили всего один отчет об этой уязвимости, хотя в первую ночь соревнований зафиксировали высокую нагрузку на систему. Она была вызвана тем, что многие участники пытались эксплуатировать эту уязвимость.

RCE-уязвимость (Remote сode execution)

Сложно переоценить опасность уязвимости, касающейся выполнения произвольного кода в таких критичных системах, как онлайн-банкинг. Однако периодически и такие бреши  встречаются . Мы  использовали одну из нашумевших уязвимостей конца 2021 года  — CVE-2021-44228, или Log4Shell, разместив в составе банка уязвимую версию пакета Log4j.  

В погоне за элегантным сценарием полной компрометации банковской системы через веб-уязвимость мы не заметили некоторые ошибки при компиляции сервиса. Таким образом, появилось два способа выполнения произвольного кода, один из которых был доступен в течение ограниченного промежутка времени в самом начале конкурса (спасибо Apache и его дефолтному DEBUG-журналированию внутри самого себя ????). В обоих случаях для эксплуатации уязвимости необходимо было использовать  PoC с GitHub .

Официальный способ

Рассмотрим постоянный способ получить реверс-шелл, эксплуатируя Log4Shell. Для этого требуется захватить один из аккаунтов администраторов, так как через их панель можно удалить любого пользователя из системы. Захватить аккаунт можно в ходе  одной из комбинаций простых атак  на банковскую систему, а сам запрос на удаление выглядит следующим образом:

Проэксплуатируем Log4j через параметр username: вставляем полезную нагрузку в параметр и получаем:

Эксплуатация прошла успешно:

Результаты задания на PHDays 11: ни один из участников не дошел до этапа эксплуатации этой уязвимости, так как им не удалось захватить аккаунт администратора.

Неофициальный способ

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

Для начала запускаем скрипт:

В BurpSuite Repeater отправляем любой запрос, который получаем от фронтенда. В данном случае это /sharedData/admins. Делаем инжект в куки запроса со своим IP-адресом, предварительно запустив сервер у себя для получения реверс-шелла:

Профит! У нас есть реверс-шелл в узле с бэкенда банка :)

Успешная эксплуатация уязвимости:

Стоит отметить, что данный способ работает всего один раз. Apache журналирует это событие с пометкой, что при его повторении оно не будет еще раз залогировано (невалидная куки). То есть воспользоваться данной уязвимостью участники конкурса могли лишь единожды с момента запуска сервиса.

Уязвимости CSRF

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

Результаты задания на PHDays 11: лишь один участник сообщил об этом недостатке безопасности.

Возможные сценарии атак, или В чем полезность конкурса

Создавая  Payment Village  на  Positive Hack Days , мы преследовали цель не только обратить внимание на потенциальные уязвимости в банковских системах, но и помочь как атакующим, так и защитникам осознать возможные последствия кибератак на банковские системы. Как злоумышленники могут воспользоваться найденными IDOR в кредитах, ошибкой округления в межвалютных переводах, слабой парольной политикой или неправильно реализованной двухфакторной аутентификацией? Сценарии атак могут быть такими:

  • Возможность перебора паролей при входе позволяет атакующим получить пароль одного из администраторов.

  • Уязвимость бизнес-логики в OTP дает атакующим возможность угадать одноразовый пароль. С его помощью они могут зайти в аккаунт одного из администраторов. В дальнейшем злоумышленники могут не ограничиваться лишь только удалением пользователей, как мы описывали ранее в статье, но и, к примеру, воспользоваться Log4Shell для проникновения в инфраструктуру банка.

  • Грамотное применение ошибки округления, а также автоматизация валютных переводов между своими картами может сделать злоумышленников богачами (участников нашего конкурса так уж точно ????).

  • Ошибка в бизнес-логике в OTP и  CSRF-уязвимость  позволяют атакующим сменить данные в ходе атаки на двухфакторную аутентификацию и привязать свой Telegram-аккаунт к личному кабинету легитимного пользователя без какой-либо верификации. Отсюда следует, что жертва не сможет самостоятельно войти в свой личный кабинет — это можно будет сделать, только обратившись за помощью к представителям банка.

Заключение

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

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

Больше о Payment Village можно узнать в  Telegram . До встречи на следующем форуме Positive Hack Days!

Автор в Telegram: @geralt_iz_rivii

positive hack days онлайн-банк финансы уязвимость райтап positive technologies ошибки округления idor rce csrf
Alt text

Ваша приватность умирает красиво, но мы можем спасти её.

Присоединяйтесь к нам!