不特定多数の方に開放したホームページ上で販売を行うネットショップ・オンラインショップにおける電子商取引では、ユーザーの入力情報を保護する事が必須であり、更に外部からの攻撃に備え十二分な対策を講じる必要があります。
<< cookie以外のHTTP仕様には「proxyの壁」がある
つまり、ユーザーが特定できないという事は、結果的にcookieへの依存度が高くなるということであり、同一セッションにおいて通常はcookieと[REMOTE_ADDR]で判定し、IPは同一だけど複数のユーザーが利用している場合やIPが毎回変わる場合はcookieだけで判定するしかないという事になります。
そこで後者の判定をせずに、cookieと[REMOTE_ADDR]で判定している場合には、万一にも同じプロクシ経由のショッピングカート利用者を識別できなくなります。
そこでエラーが発生した場合は、ユーザーが不運だっただけで仕方ないよと考える人は、まずいないでしょう。
なぜなら、善意の同一IPを持つ可能性のあるユーザーのカートの中身やユーザー登録情報にも異常をきたしますから信用問題ですし、システム側からすれば矛盾が発生してシステムエラーになる可能性もあり、場合によってはRDBのテーブル間の整合性エラーでシステム復旧を余儀なくされる可能性もあるからです。
その万一の事態を回避する為には、「cookieにのみ依存するという運用にする」か、やはり、cookieと[REMOTE_ADDR]で判定するのであれば、「IPは同一だけど複数のユーザーが利用している場合やIPが毎回変わる場合は利用不可とする運用にする」しかなくなります。
しかし、利用不可とする事はネットショップにとっては販売機会の損失ですから、利用不可とするよりはcookieにのみ依存してでも利用できるようにしたいところです。
cookie保護とセッションを狙うサイバー攻撃やcryptの説明の通り、セッションIDを暗号化しただけでは、ネットワーク上で盗み見され、そのまま利用される可能性が残ってしまいますから、SSLで保護する事になりますが、それでは最初のセッションをセットするタイミングはいつで、そのセッションをセットする際にはSSLで保護されているでしょうか?
この場合、HTMLのmetaタグで設定するか、JavaScriptなどのクライアントサイドスクリプトまたはPerlなどのサーバーサイドスクリプトを利用する事になるでしょう。
「HTMLのmetaタグで設定」する方法では、静的なHTMLファイルであっても(サーバサイド、クライアントサイドスクリプトを利用した)動的に生成されるHTMLファイルであってもmetaタグでcookieを書き込んでは外部から盗み見られる可能性もありますし、単純に「ページのソースを表示」をする事で中身が誰にでも見えてしまいます。
それを回避する為には、JavaScriptやPerlでcookieをセットしてそのままSSLで保護されたHTTPSページに遷移させる為にリダイレクトするケースも考えられます。
但し、JavaScriptを利用する場合には、ユーザーが確実にその時点でJavaScriptを許可している状態であるようなカートの仕組みが前提であり、そうない場合には、Perlなどのサーバーサイドスクリプトで処理する事になります。
前者の場合は、更に、「ユーザーが次のリクエストを出す時の通信」自体は、SSLで保護されていない事になるのでネットワーク上でcookieの中身を盗み見られる危険性が残ります。
後者の場合は、どうでしょうか?
後者の場合、前もってセットしておいた[http]用のcookieをユーザーがアクセスしてきた際に取得して、同時に[secure]フラグをセットした[https]用のcookieをセットし、そのまま指定したURLにリダイレクトしますから、ユーザーは一度しかアクセスしていませんが、実際には[secure]フラグをセットした[https]用のcookieをセットした後、改めてリダイレクト先のURLにアクセスしてきた時と同じ状態になります。
そうなるとリダイレクトが実現可能性とセキュリティを両立しているように見えますが、前者同様「ユーザーが次のリクエストを出す時の通信」は保護されていません。
それでは[http]と[https]でセッションIDを振りなおしたり、セッションIDをアクセスの都度変更すれば、善意の方に設定されたセッションIDが盗まれても効果をなくす事ができるのでしょうか?
仮にそうする場合を考えてみるとして、善意のユーザーと最初のセッション、次に発行するセッションIDとの紐付け(特定)をするにはプログラムではどのように処理する事になるでしょう?
まずは、cookieを利用し、最初に付与するセッションIDをcookieに格納してセットする。
次にアクセスしてきた際には、最初のセッションIDをチェックして、一致すれば次のセッションIDを発行する。
ここまでは特に問題はないでしょう。
しかしこの時、最初のセッションIDと次のセッションIDをcookieに仕込むとすれば、cookieを不正入手された場合に意味がありません。
それならばと、cookieには最初のセッションIDだけ、もしくは新たにセットしたセッションIDだけをセットし、DBに履歴情報を格納してプログラム的に一致をチェックする場合にはアクセスしてきたユーザーのcookie情報からは前後のセッションIDの紐付けはできませんから、cookieに格納されているセッションIDを基にDBから取得してチェックするとすれば、やはりcookieが不正入手されたかどうかの判定はできません。
となると、cookieを受け取ったら、存在確認をして存在する場合に上書きするケースまたは前のセッションを無効にして新たなセッションを適用するケースでは、前のセッションIDは存在しないか、または無効ですから、盗み見る隙を極力減らす事はできるかもしれませんが、やはりcookieが不正入手されたかどうかの判定はできません。
更にいずれのケースでもセッションを不正取得後、本来のユーザーより早く次の操作をした場合に善意のアクセス者が排除される可能性が残ります。
因みにこの時、どれだけ予測不能な複雑なセッションIDにしたとしても、善意のアクセスでも悪意のアクセスでもその「予測不能な複雑なセッションID」をプログラムが取得してプログラム内でチェックをするので善意か悪意かの見分けはつかないでしょう。
これらの対策は「瞬間的なセッションを盗み見たあと正規ユーザーよりも早く次の操作をする」という以外に悪用のしようがない点に集約できる事がメリットに見えますが、実際には、正規ユーザーか不正ユーザーかの区別がつかないので正確な不正排除になりません。
これが「善意のアクセス者が排除される可能性」です。
セッションIDをアクセスの都度変更しつつ、その時点のセッションIDをチェックすると同時に[HTTP_USER_AGENT]、[REMOTE_ADDR]のチェックをすれば、これらのチェックで排除される不正アクセスもあるかもしれません。
遷移元画面IDのチェックもしたいところですが、[HTTP_REFERER]が不確実なので、[HTTP_REFERER]を利用するチェックで排除するのは、よく考えた方がいいと思いますし、cookieとして仕込むとすれば、そもそもcookieが盗み見られる危険性がある場合には信憑性を欠く事になります。
もちろん、同一のセッションIDはない事が前提で、仮にあった場合は不正とみなすでしょう。
そうであるとすれば以降の処理は、仮に善意のセッションIDと不正入手された同一のセッションIDがあった場合、先に処理を行った方は通常処理され、後から処理をしようとした方はエラーとする事が考えられます。
しかしその場合、善意の方がエラーになる可能性もあるという事になります。
そこでIT/ICT業界やユーザーの間ではこれまでもいくつかの方法が提案されています。
例えば、「セッションIDを盗み見られないように、盗み見た時には既に意味がなくなるように速やかに購入処理を進めてもらうよう促す」といった運用上のものから「セッションIDを予測しにくいものとする」「httpとhttpsでセッションIDを動的に変更する」「遷移元画面IDも参照できるようにする」「ワンタイムパスワード」、「ベーシック認証」、「ダイジェスト認証」、「双方向ワンタイムID認証」を利用するなどです。
簡易な説明に留め、詳細は割愛しますが、これらの対策も残念ながらここで述べた理由によりセキュリティ上漏れがあったり、根本的な解決にはなりません。
「ベーシック認証」と「ダイジェスト認証」については、ポップアップにユーザーIDとパスワードを入力してもらう必要があり、「ベーシック認証」は通信が平文のまま行われる事からセキュリティを確保する為にはSSLとの併用が必須であり、「ダイジェスト認証」については対応するブラウザがない、あっても限定的なようです。
この時点で必然的に「ベーシック認証」とSSLの組み合わせが候補として残ります。
これにより「ベーシック認証」+「SSL」、またはセッションIDや他の情報と「ベーシック認証+SSL」の組み合わせなどが考えられます。
これらを採用する場合、事前にIDとパスワードを登録をしてもらう必要があり、事前にIDとパスワードを登録していないユーザーについては、問題が解消しませんし、ポップアップでIDとパスワードを求められる事に抵抗を覚えるユーザーも少なからずいるでしょう。
前述の候補の中でいえば更により有効なものは、「双方向ワンタイムID認証」であると考えられ、更に「生体認証」との組み合わせなども検討されているようです。
しかし「生体認証」が広く普及し、手軽に一般に利用できるようになるまでは相当の時間がかかるでしょう。
実は、先ほど挙げた以外にHTTP仕様には[REMOTE_USER]というアクセスしてきたユーザーを特定するのに適しているかに見える環境変数にセットされる値があります。
その[REMOTE_USER]には、「クライアントのユーザー名」を返してくれますから、更に期待が高まろうというものです。
しかし、[REMOTE_USER]は、何もせずに$ENV{'REMOTE_USER'}としただけでは参照できません、というより参照はできますが値が入っていません。
それではどうすれば[REMOTE_USER]に値が入った状態で取得できるかというと、「ウェブサーバで」前述の「ベーシック認証」「ダイジェスト認証」を行う設定をした場合に、その認証の際に入力された「ID」を「ウェブサーバが設定」してくれます(当然パスワードは格納されません)。
更にもうひとつ有望そうな環境変数である[REMOTE_IDENT]にセットされるのは、クライアント側のユーザーIDです。
[REMOTE_IDENT]という環境変数にセットされる前提条件としては、サーバーが「IDENTED認証」を実行している必要があります。
因みに「IDENTED認証」を実行しているサーバーが[REMOTE_IDENT]にセットするクライアント側のユーザーIDとは、「クライアントのOSのログインID」ですからアクセスしている全ユーザーの内、どのユーザーかを特定するには[REMOTE_USER]よりも確実に見えます。
しかし、単独で見た場合には「クライアントのOSのログインID」が一意とはならない(同じ名前があっても不思議ではない)でしょうから複合条件でチェックする事になります。
それなら使えそうじゃん!、と思ったのも束の間、「IDENT認証」はTCP/IP接続におけるセキュリティが確保できないというデメリットがあります。
つまり、インターネット上で不特定多数のユーザーに開放する仕組みには不向きという事です。
「IDENTED認証」をTCP/IP 接続を介して行う場合にはクライアントホスト上のidentサーバに問い合わせる事で「クライアントのOSのログインID」を取得する事ができます。
この場合、事前にIDとパスワードを入力してログインしてもらっておき、テーブルに格納した情報と(ブラウザを閉じても有効な)期限設定付きcookieに予めIDとパスワードのキーとなる値をセットしたものと照合する必要があります。
但し、「IDENTED認証」ではポート[113]が開いている必要があり、また、クライアントを全面的に信用している状態で運用される事から、悪意のあるアクセスがあった場合に困ります。
論理的にはパケットがポート[113]を通過する前に善意のアクセスか悪意のアクセスかをチェックする必要がありますが、物理的には無理でしょう、こうした事が可能であればポート[80](HTTP)などに対する他の攻撃も心配する必要はないはずだからです。
つまり、TCP/IP 接続と「IDENTED認証」の組み合わせでは、クライアントマシンが常に信頼できるという環境下でしか安心して利用できませんから不特定多数のアクセスがある場合にはセキュリティを確保できません。
ただ考えようによっては、他のポートと同様、ポートを監視する事によって不正アクセスを事後検出する事は可能になりますし、他のHTTP仕様と組み合わせれば、プロクシを使っている場合はプロクシのIPを特定、プロクシを使っていない場合はIPを特定した上で「クライアントのOSのログインID」を取得する事ができるので端末が特定できる事になり、悪意を持ってアクセスしようとする側に対して抑止力になるともいえますし、それでもアクセスしてきた場合は法的措置を講じる事もできなくもなさそう?と考えるのは詰めが甘いかもしれません。
なぜなら、DDoS攻撃の場合と同様に、たとえ[REMOTE_IDENT]「クライアントのOSのログインID」の改ざんの可能性が皆無であったとしても、悪意はなくとも脆弱性を抱えた世界中のネットワークにつながるPC端末を踏み台にした攻撃であった場合には、特定したはずの情報でも悪意あるアクセス者にたどり着く事は現状では非常に困難だからです。
「ユーザーを唯一、一意に特定できない」「セッションハイジャックを完全に排除する術がない」状況においては、前述の対策を講じた方が安全性が多少なりとも高まりますし、入力情報自体の保護対策はできても、セッションハイジャックを含むサーバ攻撃を完全防御する事はできず、それによって間接的に入力情報の不正流出を完全に防ぐ事ができないと考えられます。
「ユーザーを唯一特定できる方法」を確立しようにも、悪意あるアクセス者の事を考えるとそれが悪用されては困ります。
これが、悩ましい点です。
ショッピングカートに必要な品質確保する為の大前提の対策。
セキュリティを考える上でショッピングカートCGIの対策を講じただけでは不足です。
ショッピングカートCGIで利用する複数のファイルと公開するウェブサーバ上のセキュリティ設定とディレクトリ保護、ウェブサーバへのアップロード、ターミナルエミュレータ利用におけるセキュアな接続なども必要です。
また、ログインID、パスワードはセキュアなウェブサーバ、セキュアなFTPソフト、セキュアなターミナルエミュレータにおいても徹底管理が必須です。
ネット上でショッピング機能を利用する場合、「一連の操作をしているユーザー」を特定する為にはcookie/クッキーの設定が不可欠です。
ここまでのセキュリティは最低限必要であり、cookieの実装によりショッピングカートを一応組み込む事はできますが、残念ながら完全にセキュリティが確保されるわけではありません。
また、善意のアクセスの拒否か、またはセキュリティ確保の二者択一を迫られるケースもあります。