Как не нужно интегрировать платёжные системы
А Вы тоже доверяете своим программистам? Мы идём к Вам!
Внимание: данную статью не следует воспринимать как руководство юного хакера; материал приведён исключительно в ознакомительных целях, чтобы программисты не повторяли подобных ошибок.
Итак, имеем платёжную форму (информация, идентифицирующая сайт, затёрта):

Ничего сверхестественного: нам предлагают купить некую услугу за $99 в месяц. Всё как обычно. Интересные вещи начинаются, когда смотришь на детали формы:

Для тех, кто не знает: сумма платежа для системы SecurePay задается как целое число (исходноё значение умножается на 100). Так, $99.00 передается как 9900, а, скажем, $20.45 — как 2045.
У любого человека, занимавшегося интеграцией платёжных систем и имеющего опыт в компьютерной безопасности, возникает законный вопрос: если скрипт перед отправкой платёжных данных обрабатывает эти самые данные, зачем помещать в форму итоговое значение, причем отформатированное для платёжной системы? Если этот человек имел дело с индопакистанофилиппинцами, то ему только остаётся схватиться за голову.
А что произойдет, если подменить значение на, скажем, 0100 ($1)? На нулевое менять нельзя, любая уважающая себя платёжка ругнётся; например, так:

Кстати, отрицательный результат — тоже результат: ошибку возвращает SecurePay, а из этого следует, что скрипт не проверяет значение суммы платежа, и ему можно скормить любое значение!
Итак, меняем сумму платежа:

И отправляем форму. В результате получаем такую картину:

Осталось посмотреть, сколько денег снялось:

Как видим, снялся $1.00 — операция прошла успешно.
Программистам (справедливости ради стоит отметить, что это были не индийцы, а румынец из компании SurgeWorks) могу сказать следующее: никогда не доверяйте данным, которые пришли от пользователя. Лень (и непрофессионализм) в этом случае могут обернуться большими потерями.
Update: чтобы ни у кого не возникало желание обвинить меня в обмане владельца сайта и взломе всяких разных сайтов, к которым я не имею никакого отношения (Jurgen, привет!): я поставил владельца сайта в известность, и мы с ним работаем над устранением уязвимости.
Вложения:
- amount-charged (image/png)
- payment-successful (image/png)
- changed-amount (image/png)
- Invalid Amount (image/png)
- Информация о форме (image/png)
- Исходная форма (image/png)
Ноя
2008
Комментарии к статье «Как не нужно интегрировать платёжные системы» (8) »
Пожалуйста, не используйте эту форму для комментирования! Данная форма предназначена исключительно для ботов.
Оставить комментарий к записи «Как не нужно интегрировать платёжные системы»
गते गते पारगते पारसंगते बोधि स्वाहा
Меня зовут Владимир, я программист-фрилансер, специализирующийся на Web-программировании и програмировании под Linux.
По совместительству занимаюсь администрированием LAMP/LNMP-серверов и техническим переводом.


Сомнительно как-то все это… Мне кажется в современных, популярных платежных системах такие трюки не пройдут…
В частности, вот кусок кода с сайта:
//...
$a = array(
'merchantID' => $merchantID,
'password' => $password,
'amount' => $params['a'], //Вот оно пришло с формы - безо всяких проверок
'clientID' => $clientID,
'currency' => $currency,
'cardNumber' => $params['cc'],
'cvv' => $params['cvv'],
'expiryDate' => "{$params['expiry_date']['month']}/{$params['expiry_date']['year']}"
);
$xml = xmlForAddingTriggeredCreditCardPayment($a);
// Add customer to Securepay!
$response = securepayXMLtoArray( securepayProcess($payment_url, $xml, $debug) );
Программёр сэкономил три строчки:
$amount = $membership->trial_days > 0 ? $membership->trial_price : $membership->fee;
$amount *= 100;
А заказчик «нагрелся» на $98 с первой же попытки.
Чтобы не было путаницы с терминологией: SecurePay — это платёжная система, а скрипт, это та хрень, в которую интегрирована работа с SecurePay.
С нашими Яндексом и Webmoney, такое, по-моему, не прокатит.
Всё зависит от внутренней реализации скрипта.
мне кажется что это рыба… Ну уязвимость конечно есть, но несущественная, сам имею похожую форму pay pal можно заплатить за заказ 1$ пожалуйста, только вам его никто не доставит, ну получили мы платеж на 1$ ну клиент спрашивает, де мой 600 мерседес? а мы спрашиваем де наши 30 000$ вот собственно и все… Результата никакого, кроме создания сотрудникам гемороя
Андрей, это на membership-сайте. Пользователь платит за контент. Как только платёж прошел, он получает доступ. Пока (и если) владелец сайта обнаружит, что пришёл неверный платёж, пользователь успеет скачать всё, что нужно.
Ну вот смысл подписываться на комментарии, если почтовый сервер делает hard bounce?