Потенциальная уязвимость в безопасных платежах при размещении на хостинге службы
Я реализую простой магазин для приема платежей. Я использую решение для хостинга. Как это работает:
- Моя страница занимается созданием корзины покупок. Когда придет время брать деньги, моя страница будет перенаправлена в размещенный магазин.
- Размещенный магазин будет обрабатывать транзакцию.
- Размещенный магазин перенаправит мне результаты.
Я хочу убедиться, что транзакции выполняются максимально гладко и безопасно. Документация для магазина делает процесс довольно простым. Все, что действительно нужно отправить поставщику магазина, приведено ниже, взято из их документации.
<FORM METHOD="POST" ACTION="https://www.fakehostedstore.com/xxx/index.php">
<INPUT TYPE="HIDDEN" NAME="store_id" VALUE="abcdefg">
<INPUT TYPE="HIDDEN" NAME="store_key" VALUE="hijklmnop">
<INPUT TYPE="HIDDEN" NAME="charge_total" VALUE="100.00">
<!--MORE OPTIONAL VARIABLES CAN BE DEFINED HERE -->
<INPUT TYPE="SUBMIT" NAME="SUBMIT" VALUE="Click to proceed to Secure Page">
</FORM>
Это меня несколько беспокоит. Если бы я, например, открыл что-то вроде Firebug, я мог бы изменить "charge_total" на то, что мне нравится, перед отправкой формы. Очень быстро, я мог бы уменьшить сумму оплаты, которая будет отправлена в магазин со "100,00" до "10,00". Магазин, который будет взимать плату, не будет мудрее и поступит с неверным зарядом.
Если транзакция завершается в магазине, магазин возвращает сумму, которая была успешно списана. Затем я могу проверить против моего ожидаемого заряда. Например, я ожидал 100 долларов, только 10 долларов, WTF!
Есть ли способ защитить эту форму таким образом, чтобы она была менее подвержена фальсификации?
2 ответа
Я думаю, что вы ничего не сможете сделать с этим, если они не изменят метод обработки платежей (как, например, вы регистрируете продукт в их сервисе с фиксированной ценой, и они возвращают вам идентификатор продукта, пользователь вводит номер предметов она хочет приобрести, а потом они рассчитывают общую цену на своей стороне).
Они отправляют вам обратно данные из службы (например, сумму, которая была взята)? Есть ли у вас возможность увидеть сумму, которую заплатил пользователь (значение ответа, какой-либо вызов API и т. Д.), Кроме как ждать, пока деньги появятся на банковском счете? Если нет, то их дизайн серьезно испорчен.
Что касается фальсификации, вы не можете ничего сделать, чтобы предотвратить изменение значения опытным пользователем. Это даже не обязательно делать на уровне браузера - она может использовать прокси-сервер, такой как Fiddler, для изменения HTTP-запросов.
Однако стоит ли вам беспокоиться об этом, зависит от того, что и как вы продаете. Если это какая-то платформа для немедленной продажи (например, вы предоставляете доступ к некоторым интернет-ресурсам и т. Д.), Это плохо. Если магазин представляет собой магазин бытовой техники, который отправляет вещи по почте, вы можете каждый раз проверять полученную сумму, сравнивая ее с ожидаемой (я думаю, что будет какой-то автоматизированный инструмент для поиска входящих платежей на банковском счете, поскольку обычно вы не отправляете вещи пользователю, пока не увидите, что деньги на вашем счету).
Я сразу вспомнил о себе похожую вещь, которую я когда-то читал где-то (скорее всего, на SO): в ранних интернет-магазинах вы иногда могли ввести что-то вроде 0,01 в поле "количество", а на сервере - цену. был рассчитан умножением (таким образом, вы заплатили 0,01 фактической цены!), а количество было округлено до целого числа!
Изменить: у них есть документация на ответ, который они дают? Вы пытались сделать поддельную транзакцию?
Изменить 2: Так как магазин возвращает вам списанную сумму, это хорошо. Тем не менее, это может создать проблемы (нетехнические) для магазина, потому что деньги все равно будут списаны. Вы можете отобразить информацию на следующем экране, сказав, что вы получили в 10 раз меньше, чем хотите, но вам все равно придется вернуть эти деньги мошеннику (в противном случае это будет незаконно).
Жаль, что магазин не обеспечивает какую-то обработку кода аутентификации сообщений. На самом деле, есть хороший способ предотвратить именно такие читы. Однако оба сервера должны сотрудничать в этом.
Посмотрите на HMAC. Это выглядит сложно, но идея проста. Я объясню это по упрощенному алгоритму.
У вас есть вход, скажем price=100
, Вы передаете это третьим лицам. В это время легко подделать. Но скажем, мы отправляем дополнительное поле, price_verification
, Мы можем рассчитать это, используя предварительно согласованную хеш-функцию с предварительно согласованной солью (это должны знать и вы, и платежный сервер). Затем вы рассчитываете, скажем price_verification=SHA1(price + someLengthySalt)
и отправьте его на платежный сервер. Они знают алгоритм и соль, поэтому они рассчитывают SHA1(received_price + someLengthySalt)
, Если они различаются, пользователь является мошенником, и вы отменяете транзакцию. Конечно, это безопасно, пока пользователь не знает алгоритм и / или соль, поэтому он не может легко вычислить price_verification
,
Однако соль должна быть очень сильной, а алгоритм, возможно, более запутанным, например, SHA1(SHA1(price)+salt)
так далее.). Необходимо принять во внимание, что пространство ввода цены очень мало (только числа с двумя десятичными разрядами - можно легко перебрать, если соли нет).
Это может быть легко расширено для проверки любого количества параметров (вам просто нужно договориться о том, как сериализовать данные).
Я думал, что упомяну, как магазин предлагал решить эту потенциальную проблему безопасности. Возможно, это применимо к другим, которые реализуют безопасные страницы размещенного магазина.
Магазин предлагает два способа оплаты. Первая, "покупка", сразу же берет деньги с кредитной карты. Это был метод, который я использовал. Это было легко осуществить, но не дало никаких гарантий, что с карты будет списана необходимая сумма.
Второе, "preauth", удерживает деньги на карте, но не берет деньги, пока не будет выполнена дополнительная транзакция "захвата". Добавив этот шаг, можно подтвердить предварительно авторизованный заряд перед формальной зарядкой карты. Если заряд является недействительным, то также можно снять удержание на карте.
В моем случае я делаю транзакцию "захвата" немедленно, но для бухгалтера будет возможно "захватить" все "предавты" дня вместе в пакете.