私はオンラインストアで商品の支払いに使用できるギフトカードコードを生成している会社で働いています。
これらのギフトカードコードを生成する最も安全な方法は何でしょうか。長さは16文字(交渉可能です)である必要があり、英数字にすることができます(数値の方がよりわかりやすくなります)。
私が見ることができるものから、これを行う最も安全な方法は、次のJavaコードを使用して、特定の長さのギフトカードコードを生成することです。
static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static SecureRandom rnd = new SecureRandom();
String randomString( int len ){
StringBuilder sb = new StringBuilder( len );
for( int i = 0; i < len; i++ )
sb.append( AB.charAt( rnd.nextInt(AB.length()) ) );
return sb.toString();
}
これは、スタックオーバーフローの回答 here から取得されます。ユーザーフレンドリーにするために、文字列から小文字を削除しました。したがって、これは36 ^ 16
の組み合わせ。数値だけでも10 ^ 16
の組み合わせ。私は数字だけで十分だと思いますが、ギフトカード詐欺がますます蔓延していることを考えると、文字列は英数字である必要があることがしばしば強調されます。それが問題1です:numericまたはalphanumeric?
ユーザーがオンラインストアのギフトカードを使用して商品の支払いを行うと、APIが呼び出され、ギフトカードの残高と通貨が返されます。ギフトカードのコードがサードパーティのサーバーに入力されている場合、これらのギフトカードは、これらのサーバーにアクセスできるユーザーが利用できるようになりました。これは明らかに、ユーザーが部分的に償還した後に残高が残っている場合の問題です。
1つのオプションは、残高を取得するために(ギフトカードコードを使用して)APIへの呼び出しが行われたときに、オンラインストアが使用できるランダムな文字列をストアに返して保存します。 -システムのギフトカードコードと照合します。これに関する問題は、おそらくユーザーがチェックアウト時に入力するギフトカードコードがログのどこかに記録され、それらのログにアクセスできる人なら誰でもアクセスできることです。
別のオプションは、ギフトカードのコードを部分的に利用した後で更新することです。そのため、ユーザーは基本的に残高の新しいギフトカードコードが発行され、前のコードはキャンセルされます。これはおそらく最も安全ですが、ユーザーフレンドリーではありません。それが2番目の質問です。部分的にのみ利用され、まだ価値が残っているギフトカードコードをどのように保護しますか?
編集:
また、ユーザーがギフトカードコードを入力すると通貨と残高が返される[残高の確認]ページもあります。これはおそらくいくつかの追加のセキュリティ問題を作成します。
不正を防止するには、攻撃者がanyの有効なコードを推測する可能性を十分に低くする必要があります。 100万枚のカードの場合、10 ^ 16回の試行ごとに平均して10 ^ 16コードが推測されます。サイトが完全に安全であり、APIがブルートフォースに対応している場合、詐欺へのそのアプローチを費用効果の高いものにしないためには、数値で十分です。
しかし、これは非常に脆弱なセキュリティであり、以下のハッシュ保護は、このような小さなキースペースでデータベースリークを簡単に破ることができます。 IOW、DBへのアクセス権を持つ攻撃者は、多くの有効なコードを総当たりすることができます。英数字コードは、より堅牢なセキュリティを提供します。また、ユーザーフレンドリーなパターンを使用して妥協することもできます。
あなたのシステムではコードは事実上ログインとパスワードの両方であるので、それらの漏洩を減らすために、通信プロトコルを変更して平文コードの送信と保存を排除する必要があります。
そのための最も簡単なプロトコルは、Salt1とSaltHash1 = hash(Code + Salt1)を格納し、Salt1をクライアントに送信し、クライアントでSalt2を作成し、hash(hash(Code + Salt1)+ Salt2)を生成してクライアント側でチェックすることです。ハッシュ(SaltHash1 + Salt2)に対するそれ。
攻撃者が実際に有効なSaltHash1のリストを必要とするのはAPIを介して購入するだけなので、データベースが危険にさらされている場合でも脆弱です。また、有効なコードをすべてハッシュしてチェックする必要があるため、処理が遅くなります。
より堅牢にするために、Argon2idのようなPBKDFですべてのコードを変換することができます。これは、低速で不可逆的な関数であり、結果のみを保存します。遅い関数を使用すると、データベースが漏洩した攻撃者がすべての10 ^ 16コードを簡単に総当たりして合法的なユーザーをシミュレートすることはできません。それでも、コードを保存せずにHSTS(httpsのみ)接続を強制するためにストアを信頼する必要があります。
このシステムを、ユーザー入力をログに記録する悪質なストアから保護することは不可能です。ユーザーが完全なコードを持っている場合、それらは定義によりownカードです。唯一の防御策は、サーバーから直接ロードされたフォーム(サードパーティのページに埋め込むことができる)を通じてのみコードの引き換えを許可することです。これを行うと、ユーザーとPBKDF以外にはコードが表示されません。ストアは検証応答を取得するだけです。
ギフトカードのコードがサードパーティのサーバーに入力されている場合、これらのギフトカードは、これらのサーバーにアクセスできるユーザーが利用できるようになりました。
サーバー管理者がギフトカードにアクセスできることは事実ですが、ユーザーがオンラインストアに入力したクレジットカード番号にアクセスすることもできます。悪質な操作を行わずにオンラインストアでクレジットカード番号を収集できると信頼できる場合、ギフトカードIDの収集も信頼できないのはなぜですか。 (または、管理者がCC番号を盗んだとき、それはあなたの問題ではないと考えているかもしれませんが、ギフトカードのコードを盗んだ場合、それはあなたの問題です...).
購入のたびにギフトカードのコードを変更するという考えはうまくいくはずですが、新しいコードをユーザーにどのように伝えるのですか?取引を通知するメールを送ったり、残高を含めたり、ログインして新しいギフトカードIDを取得するためのリンクを提供したりすることができます。ただし、一部のユーザーにとっては少し煩わしいかもしれません。それは実際には商人がどの程度信頼できるかによって異なり、ユーザーが最もよく知っているかもしれません。おそらく、ユーザーがリセットオプションを有効にするかどうかを決定できるようにしたり、それを超えるしきい値(たとえば、50ドルなど)を設定したりすることもできます。
技術的に対応できない根本的な問題があると思います。ほとんどの確立された詐欺対策はリスクを軽減しますが、詐欺が発生することを受け入れる必要があります。
これは基本的に信頼の問題です。各トランザクションのギフトカードから正しい金額を引き落とし、ユーザーが承認したトランザクションのみをポストすることをストアに信頼しています。また、ユーザーがカードを秘密にしておくことを信頼しています。
信頼の問題には監査が必要です。クレジットカードと同様に、サードパーティによる誤用の可能性があります。クレジットカードを取り巻くPCI DSSルールの多くは、詐欺のリスクを最小限に抑えるように設計されていますが、クレジットカード業界は詐欺のリスクに直面しています。このリスクに対処するために、銀行は不正の兆候を監視し、カード所有者は明細書を利用できるので、不正な取引がないかアカウントのアクティビティを確認できます。不正のリスクを排除することはできないため、アクティビティを監視して報告し、ユーザーが同じことを行えるようにする必要があります。 。
監視と応答性が唯一の長期的なソリューションです。合理的なセキュリティ対策にもかかわらず、不正行為を完全に防ぐことはできません。これが可能であれば、クレジットカード業界は年間数十億ドルを節約するでしょう。彼らはそれを行うことができず、あなたの会社もおそらくそうしないでしょう。会社とユーザーは不正行為を監視し、必要に応じて是正措置を講じる必要があります。 会社がギフトカードを発行する場合、プログラムの存続期間中、詐欺防止の人員配置を約束する必要があります。訴訟を起こさなくても、あなたはあなたのユーザーに救済策を提供することが期待されます。誰かが詐欺の主張を調査し、裁定する権限を与えられなければなりません。
実装できるセキュリティ対策が確立されています。ほとんどのギフトカードは残高がゼロから始まるか、販売されるまで無効です。アカウント番号またはCVVは、販売されるまで非表示にする必要があります(不正開封防止パッケージに封印されているか、スクラッチオフの背後にある)。販売時点でのアクティベーションは、ギフトカードIDではなくシリアル番号に基づいており、ギフトカードIDはそのシリアル番号から識別可能な方法で導き出されたり、その逆は行われません。
シークレットは共有され、ほとんどのセキュリティが破られます。ギフトカードと従来のクレジットカードでは、ユーザーはサードパーティの販売者になりすましに必要なすべてのものを提供します。これは、ユーザーが秘密を秘密にしておくことができるブロックチェーンベースのシステムとはまったく対照的です。根本的に安全ではないシステムを扱う場合、それらのリスクを補う制御または緩和策を実装する必要があります。次に、残っているリスクと兵士を受け入れます。
クレジットカードの世界では、顧客がブラウザにカード番号を入力する各オンライントランザクションには、カード番号[〜#〜] and [〜#〜] CVV2コードが必要です。これは通常、カードの裏面に印刷されている3桁のコードです。商人は[〜#〜] never [〜#〜]この番号を保存することをお勧めしますが、(非常に厳しい制限の下で)カード番号を保持できます。
類推は、カード番号はユーザー名のようなものですが、CVV2はパスワードのようなものです(多分、多分!)。あなたの問題は、カード番号のみに依存しているようです。これは、セキュリティのみをユーザー名に依存しているようなものです。これは問題です。カードを認証するために何らかの方法が必要です。カード番号は単なる識別子です。
私の提案は、何らかのPINをトランザクションに追加することです。お客様は、承認される前に、API呼び出しでPINを提供する必要があります。そのPINを販売者のログに保存しないでください。これが心配な場合は、トランザクションの実行時に顧客にSMSを送信するワンタイムPIN(OTP)を作成してみてください。ただし、複雑なヒープロードが追加されるだけでなく、業者が再利用するリスクもなくなります。別のトランザクション用のカード。OTPはないからです。
カード番号を変更することはさらに難しいことであり、そしておそらく最良のカスタマージャーニーではないので、お勧めしません。
私はすべての返信を調べ、提案を考慮に入れて解決策を考え出しました:
ユーザーに送信するリンクを生成します。リンクで送信されるキーはランダムな英数字の文字列であり、ハッシュ化されているため(MD5または類似のもの)、DBに保存する前に元に戻すことはできません。
ユーザーがリンクをクリックすると、リンク先ページにリダイレクトされ、キーを使用して注文を取得し、注文のステータスとクレジットがあるかどうかを確認します。問題がない場合は、16文字の長さの英数字コードを生成し、 UIに送信します。 16文字のコードがハッシュされ(ここでもMD5)、データベースに保存されます。ユーザーがリンクをクリックするたびに、その場で生成される新しいギフトカードコードが表示されます。
オンラインストアとの契約では、ギフトカードコードをどこにも記録または保存できないことを明記しています(2つのクライアントは有名なオンライン小売業者です)
クライアントのオンラインストアチェックアウトページで、ギフトカードコードで支払うには、16文字のギフトカードコードを入力します。それは私たちのサーバーに送信され、残高とランダムな支払いI.D.オンラインストアに戻されます。この支払いIDは、注文の一部としてオンラインストアに保存されます。注文が完了すると、オンラインストアはAPIリクエスト(支払いIDを含む)をサーバーに送信して、ギフトカードの金額を引き換えます(この機能は当社が構築し、インストールしたプラグインを介してオンラインストアに提供されます)。
オンラインストアとAPI間の通信は、OAuth 2.0を使用して認証されます。
ギフトカードの残高が残っている場合、新しいギフトカードコードが生成されます(ユーザーには、残高の新しいギフトカードコードを取得するための新しいリンクが送信されます)
オンラインストアが請求を行うと、支払いIDのリストが提供され、バックエンドのギフトカードコードと照合されます(発行者と照合されます)。
保護:
ギフトカードコードはメールに送信されません-リンクのみ(バックエンドでは、いくつかのチェックを行うことができます-注文の期限が切れている、ギフトカードコードを表示する前にクレジットが使い切られているなど)
オンラインストアのDBにアクセスできる人には、ギフトカードコードが表示されません
私たちのデータベースをハッキングした人は、(ハッシュ化されているため)ギフトカードコードを見ることができず、(リンクのキーがハッシュされているため)ギフトカードコードを表示するためのリンクを生成できません
コメントがあれば教えてください。