Обработка атаки проверки карты — часть 2

«В предыдущей статье я рассказал о некоторых проблемах, с которыми мы столкнулись при атаке с проверкой карты. Краткая версия была такой: однажды наша платежная система была закрыта, потому что какой-то нехороший человек из Латвии придумал способ подкинуть нам большую базу данных номеров кредитных карт, прежде всего для того, чтобы отсеять те, которые все еще были действительны, так что они могли перейти к более крупным платежам. То, как они это сделали, похоже, включало в себя автоматизацию браузера для фальшивой записи данных в платежную форму (которая использовала iframe, размещенную нашим платежным провайдером), а затем получение платежного токена для отправки на нашу конечную точку для официального запроса платежа.

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

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

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

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

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

Вопрос был: как?

Для обычного человека, использующего браузер, это было невозможно. Тем не менее, поток вокруг CAPTCHA, и особенно переключение блокировки обратно на CAPTCHA после сбоя, все происходило в JavaScript. Итак, мы проверили: что, если бы мы могли использовать инструменты разработчика Chrome для перехвата скрипта и переопределить некоторые функции, чтобы обратное перенаправление на CAPTCHA никогда не происходило? Оказывается: это было вполне возможно — мы могли добавить точку останова и переопределить функцию, чтобы обойти критическую логику. И поэтому: как разработчик приложения вы должны исходить из того, что JavaScript можно использовать с абсолютной злонамеренностью для управления небезопасным потоком данных через конечные точки вашего приложения.

Я все еще обдумываю последствия этого для одностраничных приложений, таких как Angular и React. Однако принципы просты:

  1. Не доверяйте своему JavaScript — помимо XSS-атак любой браузер с инструментами разработчика может изменить логику на стороне клиента. Поэтому;
  2. Любая логика управления потоком, необходимая для обеспечения безопасности, должна управляться на стороне сервера. Не думайте, что логика на стороне клиента будет ограничивать запросы к серверу.

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

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

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

Поэтому мы внесли еще один набор изменений, которые пошли немного дальше.

  1. Измените CAPTCHA и проверку карты, чтобы использовать сеансы для блокировки, поэтому для каждой CAPTCHA будет разрешена только одна проверка карты.
  2. Измените поток приложений, чтобы регистрация включала несколько страниц и обычные HTTP-запросы, а не JavaScript. Строго говоря, это может не иметь значения, поскольку логика сервера верна, но мы могли бы усложнить им задачу — и это будет так, потому что страница будет все время перезагружаться.
  3. Измените ограничение скорости, чтобы использовать fail2ban гораздо более явно и напрямую. Раньше мы использовали nginx для ограничения скорости и fail2ban для получения отчетов nginx для банов брандмауэра, но этот двухуровневый подход означал, что было легче обходить блокировки. Вместо этого мы добавили новую пользовательскую тюрьму fail2ban для прямого запрета множественных сбоев проверки карты.

Последний пункт связан с небольшой тонкостью конечной точки проверки. Мы хотели, чтобы HTTP-запрос имел код состояния, который мы могли бы обнаружить в журналах, но мы также хотели, чтобы проверка карты следовала шаблону POST-REDIRECT-GET. По сути, нам нужна была переадресация ошибка, отличная от переадресации успешно. (Да, мы могли бы поместить разницу в значение сеанса, но fail2ban не может видеть информацию о сеансе, только журналы доступа и ошибок).

Наше решение состояло в том, чтобы заставить неудачные POST-запросы (и только неудачные) возвращать код состояния 400 и страницу, которая включала перенаправление JavaScript на страницу с ошибкой, а не обычный ответ статуса 303. Это не строгий шаблон P-R-G, но он работает достаточно хорошо, а статус 400 в журналах означает, что fail2ban может найти и заблокировать повторные проверки карты с одного хоста.

И пока это, кажется, держится. Я не могу рекомендовать fail2ban достаточно высоко для этого. Если вы не используете его (или что-то подобное), вы подвергаетесь серьезному риску.

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

Доктор. Стюарт Ватт — когнитивист и разработчик программного обеспечения. Он является техническим директоромTuralt, компании, занимающейся искусственным интеллектом в Торонто, которая использует обратную связь и аналитические инструменты, основанные на искусственном интеллекте, психолингвистике и психометрии, для устранения недопонимания в Интернете в бизнесе.