メインコンテンツにスキップ
ブログセキュリティ顧客の財布を守るためにクレジットカード情報をパッドで保護する

顧客の財布を守るためにクレジットカード情報を保護する

ライトアップされたデータ・ネットワークの前にある南京錠のイラスト:"顧客の財布を守るためにクレジットカード情報を南京錠で保護する"

第二次世界大戦の暗号解読の教訓を、自分のウェブ・アプリケーションに応用できる機会はそうそうないだろう。しかし今日は、まさにそれを実践しようというのだ。実際、アラン・チューリングがエニグマ・マシンを破るために使用したのと同じ方法で、現代の最も強力な暗号ツールの一つでさえ、チューリングが発見したのと同じ間違いを実装者がメッセージ送信で犯した場合、当時の最も強力な暗号ツールであったエニグマ・マシンを破ることができる方法を見ていきます。

第二次世界大戦で連合国が枢軸国を打ち負かすのに役立った問題をどのように回避したのか、私が最近評価したAPIを見てみよう。

eコマースAPI:かなり甘い蜜の壺

今日取り上げるのは、あるeコマース企業の決済用APIの例だ。攻撃対象として、悪意のあるアクターにとってクレジットカード決済APIほど価値のあるものはない。そのため、この企業はAPI利用者が決済処理のために送信されるすべてのクレジットカード情報を暗号化できる公開鍵を世界に公開することにした。

その通り、このフォームで送信されるデータはすべて暗号化され、プレーンテキストで送信されることはない。カード番号だけでなく、すべてのデータを攻撃から守ることが重要だからだ。有効期限とCVVは、特定の支払い方法をユニークなものにするパッケージの一部であるため、この会社はこれをすべて暗号化していた。同社は平文で送信することはない。

チャールズ・プロキシを使い、マン・イン・ザ・ミドルとしてトラフィックを捕捉している:

この例では、paymentHashとcvvHashという2つのハッシュ値が渡されていることに注目してほしい。この2つの値に含まれるデータについて考えてみよう。

paymentHashには、このAPIで使用するために公開されている公開鍵を使って暗号化された16桁のクレジットカード番号を指定する。明らかに、暗号化に利用できる値には多くのバリエーションがあるだろう。

cvvHashについては、同じ状況はまったくありません!CVVは3桁しかありません。もし3桁の組み合わせを暗号化するだけなら、攻撃者はたった1,000の異なる値(3桁それぞれに10ずつ)の完全な辞書を構築することができる。その辞書を使えば、このAPIを経由して送信されたあらゆるカードのCVVを見つけることができる。幸運なことに、私の顧客は既知の平文攻撃を避ける方法を知っており、ナチスを崩壊させたのと同じ攻撃を避けるために、すでにランダム化パディングを実装していた。

謎を解く

エニグマが解読されにくかったのは、メッセージを暗号化するための構造が非常に複雑で、設定が頻繁に変更されていたからである。しかし、この機械は軍事用のメッセージに使われていたため、ブレッチリー・パークのチューリングのチームは、多くのメッセージの中に予想されるテキストを探し始めた。

ドイツ軍が頻繁に送信していたメッセージの一種に天気予報があり、どのメッセージにも同じ場所に「天気」を意味するドイツ語が含まれ、その後に既知の天候が続いていた。もうひとつの例は、多くのメッセージが「ハイル・ヒトラー」で終わっていたことで、オペレーターによっては標準的な敬語を使っていた。これらの事例から、各日のプレーンテキストと設定の一部を決定することも可能であった。

この種の暗号化の脆弱性は、このeコマース会社がCVVにランダム化パディングを使っていなければ、存在し得たものである。

同じ過ちを繰り返さないために

ランダム・パッドを使用することで、同じCVVを持つ2つの支払い方法があっても、送信されたものについて何も明らかにならないようにした。以下は、同じ "777 "という値が、パッドを使用することによって異なる値に暗号化されるいくつかの例である:

$ echo -n 777 | openssl rsautl -inkey public_key.pem -pubin -pkcs
-encrypt | base64

HxsNoslY+w4PH/WSSq0ObHYwCIgEpaOUn8aTeI1ger+ZKBOban1pWLN6xPJTT2ROCCIycGupdUcuOCjUU/ZyVnZ38AOZQYLkZMnJLmOkWasynjZAQi1iXr5L94HbbE9YCUWclNzEdnpWLqYY1HmaBt90AeXIVi/ff7xSX2fCc0l19UP/jZYHqJrvMdTYexwmYdKoOc+LAZrY0wpC4cpGeUXSmbE6e69uNKs6/FuovOAcv4ElmWkYAyB7Bv3vm2BGjz53sn11/nW2eew+UnDkklEOm3EWr4sU2qSh/WChDbkAfLJGvCTDIzvARi78WKhXcr6qCfF+P2/d0WOXcyieNQ==

$ echo -n 777 | openssl rsautl -inkey public_key.pem -pubin -pkcs
-encrypt | base64

QQpNRWsPxB6hwZ1WSzpN5pujkEebh9nBwiDrframigr7fU6/wqr2405Onok9iQO0hLlN5fcQm4HJMqSH2qjw5Md68vF9JZV2llTA1WT9hBSwRWdPbMDI6JfJbrkN4ZMkYIpFD8T/I1Hi2NbyiLJZxxElIyEPh7KUEzgxgHOdjFzN9ZW3vZuvSPH2es16Jw7g2BcoWoMOfRX1skB9YBLpdODUsTLPilGafmozQrQDBskUwCNPViw1tZs/ZAfUjEsc5MLAOxNSFYybj7tTqF5wtxPNmvFvsTYDCp6FKeiU2HMtFXQ21390fC9pKeJD2c3Tn7p3Z+qPTy5MCq+7aaQpOg==

$ echo -n 777 | openssl rsautl -inkey public_key.pem -pubin -pkcs
-encrypt | base64

oIWBstBP4gwZJyeEsFb0wTUkVArO5XYQCAc8sInIdsuZTMBS1seTYuZL1wKb4+puTNHs8Iq/CDNo/p9iusr/mHRPZboqla3HWg+NLcsjCuMBc/8P7DW9bSEemEOgrSfUmQ8SZ1P0bMvtDNKdb6490oq9M0m2Z1bPbhMWF2wSu72u05v+QhTcaehiMISKzwMdoI3Er7p+izNomFloF7Kuz/z/JAJ1K5YVyHLvWDNX779EeqFbcxo+dBHMvnHlF2hBmB0a3cDaSlw6/+r2h1e0S6s851IEh5JmNElxrYUJfNRY9aDWYRjhrOAKYE/9vDPrkcEdZorK/MW+TfSfNR7JBQ==

ご覧のように、上で実行したコマンドはすべて同じだが、RSA暗号化における標準のため、出力される値はすべてまったく異なる。

優れた暗号化アルゴリズムだけでは不十分

この例は、優れた暗号化スキームを導入するだけでは不十分であることを理解するのに役立つはずだ。高度に洗練された暗号化アルゴリズムであっても、同じ入力が何度も繰り返されれば、安全に送信しようとしているデータがバレてしまう可能性があります。特に決済情報を扱う場合は、電信で送信される値を容易に推測できないようにすることが非常に重要です。

パディングが重要なもう一つの例は、パスワードの保存だ。開発者は、ユーザが送信したパスワードを自分でも読めないようにするために、優れた一方向ハッシュ関数を使う必要があることを知っている。このため、開発者はパスワードをハッシュ化する前にランダムな文字列(salt )を追加する必要があります。

結論 

ウェブアプリケーションにセキュリティを組み込むことは、非常に重要な課題です。ユーザーの機密データが簡単に解読されないようにすることは、顧客の信頼を築き、ビジネスの長寿を保証します。結局のところ、自社のサイトが顧客の支払い情報を流出させたという報道を誰も望んでいないのです。全く同じ値を何度も暗号化しないようにすることができれば、非常に基本的なミスを避けることができ、顧客のデータも安全に保つことができます。

セキュリティのベストプラクティスについては、Linodeの広範なセキュリティガイドをご覧ください!

コメント 

コメントを残す

あなたのメールアドレスは公開されません。必須項目には*印がついています。