Comments 55
Недавно мы опубликовали перевод истории программиста, придумавшего способ распространения вредоносного кода, который собирает данные банковских карт и пароли с тысяч сайтов, оставаясь при этом незамеченным.
Перевод фантазии программиста. Не знаю, зачем вы вводите читателей в заблуждение.
Первая статья сама по себе была довольно ужасна, а вторая часть это просто жесть какая-то. Поэтому у неё и рейтинг на hackernoon 7к против 160к первой. Отсутствие внятных комментарий к ней на hackernoon я могу объяснить только тем, что каждый достаточно погруженный в тему разработчик просто выкидывает свой ноутбук в окно после прочтения.
Предлагать использовать iframe для секьюрных данных… Почему не Flash, не Silverlight, не Java апплеты? Тоже же "отличные" решения. И столь же современные.
Из очевидных проблем, с которыми вы столкнётесь (простите, все не скажу, я бэкендер):
- блокирование iframe в браузере и всяких адблокерах
- невозможность использования родительских компонентов, стилей, библиотек, валидации карточных данных, обработки ошибок, предложений по партнёрским программам… Всего.
- рассинхрон загрузки на два сайта. Сама возможность того, что у вас может загрузиться сайт и не загрузиться платёжная форма — это редкостная жесть.
- если пользователь случайно заметит, что он вводит данные в iframe (который к тому же грузится с левого сайта), то он убежит в панике.
Ну и в целом можно просто забить в google вопрос "should i use iframes" и наслаждаться.
Никак не ожидал увидеть такую жесть в 2018 году.
Если вам кажется, что с этими двумя статьями что-то не так, и вам интересно, как такие проблемы решаются на самом деле, то рекомендую почитать две статьи — раз (почему это ложь) и два (что делать на самом деле).
P.S. Тем не менее, за перевод спасибо, конечно.
Ну и отдельное удивление вызывает то, что автор абсолютно не представляет себе современные механизмы интеграции с платёжным системами. Сейчас всё, что вы делаете на своей стороне — это генерируете идентификатор платежа, который передаёте при переходе на страницу банка или платёжной системы. Так работает пейпал, киви и большинство банков, включая тот же ТКС. В этом случае нигде не вашем сайте не вводятся карточные данные, и максимум что может сделать хакер — получить или подменить идентификатор вашего платежа, что не очень интересно.
Никакой контроль за «чистотой» библиотек не спасет от скриптов которые загружаются с других хостов (реклама, упомянутые GTM, fb ...). С учетом того что сейчас в тренде SPA приложения переход на оитдельную «чистую» страницу будет в большей степени ломать прилоджение чем асинхронность загрузки iframe.
С моей точки зрения процесс выглядит наоборот — раньше предлагали iframe, сейчас предлагают чистый переход. Пример с ТКС, киви и пейпалом я уже привёл — интересно, а кто делает наоборот?
А переход на страницу банка и обратно SPA не ломает — оно как у вас в кэш положило бандл, так его и обратно достанет — так что тут вопрос только в том, чтобы выставить нужное состояние при обратном переходе, что не очень сложно.
Я пока что могу предположить всего одну уязвимость у iframe в сравнении с отдельной страницей: если в тексте страницы подменить адрес то на отдельной странице клиент имеет маленькую вероятность визуально заметить подмену а в iframe даже такой возможности нет.
Но на деле часто приходится долго и упорно доказывать что можно iframe, можно отдельную страницу — но только не открытые поля которые могут читать все. Первая реакция обычно такая: больной рвётся кого-то спасать, какие-то украденные cvv…
Насчёт paypal — насколько я вижу, старое решение с iframe сейчас как раз заменяется на новое без них. Ну и цитата из пришедшего мне вчера мануала по сертификации:
Full redirect is used (excluding in-context integration) — PayPal checkout pages are not embedded, framed, or loaded within a popup or new window
А по поводу
Первая реакция обычно такая: больной рвётся кого-то спасать, какие-то украденные cvv…
Так я и не говорил, что iframe обладает какими-то уязвимостями. Это примерно как отрезать себе руки и хранить их в отдельном сейфе — всё вроде бы безопасно, но есть нюанс.
Но что если вам нужна форма у себя? Мы пока держим её на отдельном поддомене (первый вариант в статье), но очень хотим переехать на ифрейм (второй/третий варианты), а всё почему: можно не уводить юзера далеко от страницы с кнопкой оплаты (1) И не нужно расширять скоуп pci dss на эту страницу (2).
Буду только рад, если предложите мне альтернативу iframe в 2018 году =)
Ну и чтоб сразу далеко не ходить за примерами тех, кто держит форму у себя — давно в стиме покупали что либо?
С точки зрения конверсии точно хуже, а по безопасности одинаково.
По безопасности — вы больше не отвечаете ни за какие карточные данные пользователей. У вас их нет. И вам для этого ничего больше делать не нужно. Никогда.
Насчёт конверсии хочется пруфов.
Пруфов не найду, но большинство магазинов пришло от многостраничного оформления заказа к одностраничному — на каждом переходе часть пользователей отваливается.
Если iframe ваш (что предлагает автор этой статьи), то ещё как отвечаете. За другой сервер, за его аптайм и безопасность, за скрипты, которые там лежат, за внешний вид всего этого добра, и так далее.
Нет, я в первоначальном комментарии говорил про тот способ, который описан в статье, в частности это должно быть понятно по параграфу
невозможность использования родительских компонентов, стилей, библиотек, валидации карточных данных, обработки ошибок, предложений по партнёрским программам… Всего.
Если это iframe банка, то тут остаются проблемы в рассинхроне, блокировке и доверии пользователя. Но здесь, конечно, решает конверсия — и я не спорю, что, возможно, она получится выше. Нужно проверять.
Ну и повторюсь ещё раз — в целом мне решение с iframe не нравится в большей степени потому, что оно пытается достаточно криво решить частную проблему (карточные данные), когда общая — это уязвимые зависимости на всём фронте и в бэке.
Так же iframe можно перегрузить своим фейком из зловредного скрипта. Отдельную страницу если загружать ее не по ссылке, а делать переход по событию на адрес который формируется в локальной переменной JavaScript, изменить практически невозможно.
Вцелом картина такая вырисовывается. Что если доступ к веб-серверу есть у неконтролируемого числа людей, то можно изменить в обоих случаях.
А с точки зрения владельца бизнеса iframe выглядит более привлекательно. Тут важно чтобы было адекватное представление об угрозе. Чисто для инетерса можно поклацать по формам сайтов кде есть карточки и убедиться что на странице есть и открытые поля (то есть не в iframe) и скриты GTM и fb. Я просто не хочу приводить тут ссылки т.к. потом типа обвинят во взломе оно мне надо?
Я скажу так что бывал на таких сайтах где поздравление с покупкой просходило даже после того как я ввоил данные по карточке без остатка а все потому что карточка прошла валидацию и процессинг сформировал ссылку возврата на сайт — которая вообще ничего не гоыорит о статусе таранзакции.
Так же мне удивительно, что почему-то рассматривается только клиентский JavaScript. Как будто нигде на бэкенде карточные данные не обрабатываются, и как будто в других экосистемах кроме JavaScript начисто отсутствуют потенциально уязвимые зависимости. Iframe это смешное и неуклюжее затыкания одной маленькой дырки, а проблема требует комплексного решения.
Point taken. Сервер действительно порядком проще оградить от кражи данных.
Но, даже если мы говорим только о клиенте, то непонятно, почему такой упор делается именно на карточные данные. Ведь можно украсть логин и пароль к сайту (который у кучи пользователей подойдёт к другим его сервисам), можно украсть куку для доступа, персональную информацию, можно менять рекламу, собирать статистику и продавать конкурентам, перенаправлять пользователя редиректами или даже тупо майнить в браузере. Почему считается, что защищать нужно только карточные данные?
Я не вникал в детальные причины такого поведения после диагностики, но по факту пока из внутренностей GTM шло обращение к заблокированному ресурсу, блокировалось исполнение "родного" JS страницы. Может криво сам GTM подключили, может скрипт этой метрики в него криво вставили, может комбинация "ответа на запрос соединения нет, а метрика работает под GTM" оказалось такой "удачной" — я не разбирался.
Предлагать использовать iframe для секьюрных данных…
iframe банки/платежные системы используют. Обозначенных Вами проблем скорее нет, чем они есть. Плюс iframe позволяет выдержать некоторые требования. Могу ошибиться, но на память iframe помогает, например, выдержать PCI DSS в той части, что данные не проходят через ваши сервера, а идут через сервера банка. Для SPA iframe хороший вариант. iframe в 2018 также хорош для определенных задач, как и в прошлом году.
Если атакующий успешно внедрил куда-либо какой-либо код, то, в общем и целом, говорить уже не о чем.
Отдать в браузер страницу сформированную на бэкэнде без посторонних скриптов, с обычной загрузкой страницы и нативной отправкой данных на сервер. Ой, постойте, это ведь уже было, а мы нынче в 2018 году и без npm жизнь не жизнь :)
Но вот этот код
var payload = {
type: 'bananas',
formData: {
a: form.ccname.value,
b: form.cardnumber.value,
c: form.cvc.value,
d: form['cc-exp'].value,
},
};
window.parent.postMessage(payload, 'https://mysite.com');
с моей точки зрения ни при каких условиях использовать нельзя т.к. точно такой же слушатель может загрущить любой злоумышленник (например из рекламного блока) и оплучать все данные).
Почему все же лучше у экваера. Нужно учитывать что экваер кроме всего прочего обеспечивает доступ к серверу на котором хостится iframe примерно как в хранилище банка. То есть дается права на доступ по распоряжению с перечислением кто дал, когда дал, зачем, кому. Полписуются документы об ответсвенности. Чего нет на обычном сайте. Когда доступ могут иметь админы, разработчики и т.п.
Что касается всех СЕО-админок (GTM и т.п.) то там простол в интерфейсе можно настроить логировать поля Х и У с такой-то формы. Не нужно и взлома никакого.
Если загружена скажем библиотека facebook для лайков или еще для чего то там просто можно видеть что на каждый submit идет отправка событий на fb. Конечно fb не будет мелочь по карманам тырить(ТМ) но там тоже люби работают.
В статье для ввода платежных данных предлагается рисовать отдельную форму в iframe, с упрощенным внешним видом и функциональностью.
Как пользователь, я бы наоборот заподозрил что-то неладное, если вместо доверенного сайта мне подсовывают iframe, да еще и с другим доменом.
Хорошо, опустим момент про домены.
Мой основной пойнт был в том, что iframe с примитивным дизайном не внушает доверия, а наоборот, выглядит как, как будто его делали очень ленивые фишеры.
Ну на счёт дизайна и функциональности — тут да. Если уж делать свой iframe, то выделяться на общем фоне сайта он не должен. С другой стороны, пробежался сейчас ещё раз по статье и не вижу рекомендации "портить" дизайн и функциональность. Разве что отнести к ней пример валидации формы чисто на HTML+CSS, но я его воспринял просто как пример, что можно даже так.
Основной же поинт, по-моему, в том, что HTML+CSS+JS код такой формы не должен содержать сторонних зависимостей или быть собран инструментами, которым не доверяешь абсолютно. То есть в условиях нормальной для разработчика, имеющего дело с особо (в рамках проекта) чувствительными данными, паранойи должен быть написан полностью вручную, без фреймворков типа ангуляра, библиотек типа редакса, реакта или даже джиквери с лодашем, а также без сборщиков типа вебпака и даже без минификаторов, по крайней мере без ручной проверки сгенерированного кода.
P.S. Заметная деградация в дизайне/функциональности при выборе такого решения (фрейм или отдельная страница без зависимостей) может быть в паре случаев:
- разработчик недостаточно компетентен, чтобы реализовать нужный дизайн/функциональность без этих зависимостей, то есть не HTML+CSS+JS разработчик, а {framework/lib name}-разработчик.
- бизнес не готов на пару таких страничек тратить ресурсы сравнимые с ресурсами нужными на нескольких десятков обычных.
Возникает вопрос: если получается сделать важную форму оплаты на ванильном JS без фреймворков, то зачем их тащить на остальные части сайта?
Тогда уж проще использовать свой велосипед для валидации на всех формах, и обойтись без заворачивания в iFrame совсем.
Предполагается, что остальному сайту нужно более сложная логика чем валидация двух-четырёх полей с крайне редко меняющимся форматом и на ванильном JS это займёт в разы больше времени чем с фреймворками. Даже если свой велосипед валидации идеально прикручивается к фреймворку без костылей, то придётся его делать достаточно универсальным.
Обычно как раз-таки форма оплаты является наиболее сложной. Помимо данных карты, там обычно еще спрашивают номер телефона, адрес доставки и т.д. И все это должно сабмититься одной кнопкой. Как одновременно засабмитить iframe, в который мы вынесли данные карты, и родительскую страницу с остальными данными?
Можно, конечно, вынести данные оплаты на отдельную страницу и оформить отдельным шагом. Но в этом случае iframe не нужен совсем. Главное очистить эту страницу от лишних скриптов.
По-моему опыту, форма оплаты как раз самая простая обычно, по сравнению с формой оформления заказа или формами основных бизнес-процессов. Да, это отдельный шаг, но в случае SPA вынос на отдельную страницу не очень вариант.
Хотя, по большому счёту iframe или страница — это прежде UX/UI-решение. Технически и административно главное отделить работу с особо чувствительными данными от остальных, вплоть до полностью изолированного контура разработки и эксплуатации, куда не имеют доступа рядовые разработчики и админы.
Рассказ о том, как не дать мне украсть номера кредиток и пароли у посетителей ваших сайтов