Вот сценарий. У клиента уже есть сайт электронной коммерции, где он собирает информацию об адресе доставки и данных кредитной карты. Тем не менее, они подписываются на услугу SaaS, которая позволяет им легко менять форму своей кредитной карты также собирать полные имена и электронные письма (не информация о кредитной карте) в маркетинговую систему для других целей. Таким образом, они вставляют фрагмент jQuery на свою страницу из службы SaaS и добавляют некоторые атрибуты «data-» в свою форму и теги полей формы, чтобы служба SaaS знала, что перехватывать и где в какую учетную запись SaaS отправлять данные.
Хорошо, но тогда возникает проблема безопасности. Допустим, у нас есть два отдельных клиента в этой системе SaaS. Один из них называется Джек и владеет jack.com, а его идентификатор учетной записи — 100001. Другой — Нэнси, nancy.com и 100002. Джек может добавить фрагмент в свою форму и добавить некоторые атрибуты «data-», но затем испортить и установите идентификатор своей учетной записи в одном из этих атрибутов данных на 100002 вместо 100001. Это будет означать, что Нэнси внезапно увидит данные Джека в своей учетной записи. Нехорошо! Исправление, конечно, заключается в том, чтобы в учетной записи Джека SaaS были некоторые настройки, чтобы он принимал данные только с jack.com, а Нэнси — только данные с nancy.com.
Но тогда случается потенциальный подвиг. Все, что нужно сделать хакеру — это создать поддельную страницу на своем собственном сервере, где он формирует аналогичный JSON и, через изменение файла / etc / hosts на своей рабочей станции, создает впечатление, что он jack.com. Затем он мог бы отправить тысячи и тысячи фиктивных маркетинговых данных в учетную запись Джека, потому что служба SaaS считает, что она исходит от jack.com.
Могу ли я что-нибудь сделать в коде jQuery или в PHP-коде, используемом сервисом SaaS, чтобы гарантировать, что хакер не сможет подделать подобное и что будут отправлены только данные реальных клиентов Джека?
ОТВЕТЫ НА ВОПРОСЫ
Q1. «Как вы идентифицируете Джека и Нэнси? По домену?»
A1. Джек имеет свой домен jack.com. У Нэнси есть свой домен nancy.com. Каждый из них использует эту маркетинговую услугу SaaS, но каждый также использует форму электронной коммерции, которую он уже имел до того, как подписался на услугу SaaS. В документации по SaaS им было сказано: «Просто поместите scraper.js на страницу формы и добавьте эти теги данных в тег формы и ввод HTML, textarea и выберите теги, чтобы scraper.js мог перехватывать отправленные формы временно. Соберите маркетинговые данные (скажем, полное имя и адрес электронной почты) из этой формы, а затем дайте этой форме отправить в свой рабочий процесс, который у вас уже был. Атрибуты данных будут определять, какой аккаунт будет использоваться, а также какой маркетинг кампания и дополнительная кампания, где эти данные должны храниться в службе SaaS. » Однако в jQuery из scraper.js он собирался передать в JSON свойство location.href, чтобы он знал, какой домен использовался — jack.com или nancy.com, в данном конкретном случае. Проблема в том, что location.href может быть подделан хакером, который устанавливает на своей рабочей станции запись в файле / etc / hosts 127.0.0.1 для jack.com и запускает копию того же кода JSON.
Q2. «Что если бы вы могли использовать механизм обратного вызова с SaaS.com на jack.com? Итак, один из ваших атрибутов данных будет указывать функцию обратного вызова для получения данных с SaaS.com, а затем сохранять данные только тогда, когда они получат ответ?»
A2. Теперь это интересный дубль. Да, так что я мог бы добавить дополнительную страницу PHP на jack.com, которая выдает «ОК». Когда SaaS.com получает сообщение данных JSON от jack.com, он отправляет запрос на эту вторую страницу обратного вызова PHP на jack.com с помощью file_get_contents (), чтобы убедиться, что он не только возвращает ответ OK, но и получает соответствие по IP адрес и данные SSL сертификата. Если они разные, то, скорее всего, запрос был фиктивным хакерским запросом, и транзакция может быть зафиксирована и отклонена. (Я могу легко проверить IP-адрес, но не уверен, как проверить те же два SSL-сертификата в PHP, если это даже разрешено или возможно.) Конечно, IP-адреса могут быть подделаны.
Еще один уровень безопасности в том, что эта вторая страница PHP может использовать проверку обмена открытым / закрытым ключом между SaaS.com и jack.com вместо простого «OK».
Q3. «Почему вы хотите перехватить информацию о платеже и отправить ее через Javascript?»
A3. Точно нет. Никогда не указывал отправку платежной информации в этом вопросе. Вместо этого говорил что-то вроде полного имени и адреса электронной почты. Да, для безопасной отправки этих данных также необходимо использовать связь SSL. И мы должны использовать JSONP, чтобы обойти проблему CORS.
Q4. «Разве для этого не требуется, чтобы jack.com сохранял все данные в базе данных для проверки? Если так, зачем использовать приложение SaaS?»
A4. Нету. Не за что. Проверьте ответ A2. С этим механизмом приложение SaaS получает данные, но не доверяет им, пока не произойдут 2 события:
Он перезванивает jack.com на вторую страницу и гарантирует, что полученный ответ имеет тот же IP-адрес, что и тот, который отправил данные формы в первую очередь.
На второй странице он проверяет обмен открытым / закрытым ключом (который, очевидно, хакер не может подделать, если у него нет доступа к серверу), чтобы убедиться, что подмена IP не произошла.
Q5. Подождите минуту. А2 и А4 имеют проблемы. IP-адрес исходного запроса на отправку будет с рабочей станции пользователя, а не с сервера. Таким образом, вы не можете проверить IP таким образом. Вам нужно будет использовать другой механизм для проверки того, что кто-то заполнил форму на jack.com и что она не была взломана хакером jack.com.
A5. Вы абсолютно правы. Я забыл об этом, я думаю, потому что я немного отвлекся на другой проект. Я должен еще подумать над этим.
TL; DR: если вы используете чисто клиентскую интеграцию (только javascript), нет способа полностью защитить запрос.
Вы можете уменьшить это, используя непоследовательные, случайные UUID в качестве идентификаторов учетной записи. Например, если идентификатор учетной записи выглядит как 100001, то кто-то может попытаться использовать идентификатор учетной записи 100002; однако, если идентификатор учетной записи выглядит c3f80e491d44cd91664a0459a0777ed01
Статистически маловероятно, что кто-то сможет отправить данные на неизвестный аккаунт.
Это проблема с любой формой, которая хранит данные в Интернете; Я не знаю, как обойти это без помощи какого-либо серверного кода.
Вы можете сгенерировать одноразовый токен, который будет включен в полезную нагрузку json — это может быть что-то вроде устаревшего токена JWT, защищенного с помощью HMAC, или установленного сообщения, зашифрованного с помощью общего секретного ключа, который затем будет сброшен сервером SAAS ,
Если вы собираетесь начать использовать программирование на стороне сервера, то этот дополнительный процесс согласования становится немного неактуальным — гораздо проще просто дать сайту электронной коммерции ключ API и позволить им публиковать информацию о клиентах, когда они получают Заказ.
Других решений пока нет …