3Dセキュア認証を初めて体験した感想
技術的な話題ともいえなくないのでこちらに書くことにする。ただし、専門家ではないので細部に渡って内容を検証しているわけではなく、あくまで利用者の視点で書いているということを了承いただきたく。
3Dセキュア認証とはここ (ZeusのWebページ)にも説明がある通り、カードの認証にカード番号、有効期限に加え、当該カード会社のWebサービス上に登録していたパスワードの入力を要求するものだ。
正直言って血の気が引いた。なぜって、パスワードの入力時に一旦カード会社と思しき別のドメインのページにリダイレクトするからだ。
このリダイレクトに関して、ベリトランスのページには次のような説明があった。
(前略)
3Dセキュア(3-D Secure™)はなぜ安全なの?
いずれのサービスも、発行カード会社に事前登録したインターネット専用パスワードを利用して、 購入者がカード所有者本人であるかを、発行カード会社が直接確認・認証することで、 第三者のカード不正使用を防止する仕組みとなっています。 なお、ユーザーにより入力されたパスワードは、クレジットカード発行会社に直接暗号化送信されるため、 ECサイトでは取得できない仕組みになっており、店舗での情報漏洩等による事故も防ぎます。
で、実際に利用してみてどのドメインに転送されるのかと思ったら、わけのわからない securesuitejp.net というあからさまにフィッシングと見まがえそうなページに到達してしまった。
これは正直ひどい。
まず、パーソナルメッセージとはなんなのだろうか。パーソナルという名前から、ユーザがここに自由にメッセージを設定できることが想定されていて、ユーザがこのサイトをオーソライズするために使う「共通の秘密」なのだろうと察せられるが、「UFJカードWebサービス本人 認証サービス」などというセクシーでもなんでもないフレーズを設定した覚えは毛頭ない。で、前出のベリトランスのページには次のような説明がある。
※パーソナルメッセージとは
カード発行会社からの正規のパスワード入力画面であることを、カード会員が確認するための確認項目です。カード発行会社により設定の有無があるほか、設定方法も異なります。
それって意味ないじゃん!!!!!
気を取り直して、このページの「ヘルプ」をクリックしたところ、ヘルプのダイアログが JavaScript を用いたポップアップで表示された。JavaScript を有効にせよ、という前置きもなく*1である。これだけ怪しければ JavaScript を有効にしないで利用するユーザがいてもおかしくないと思うのだが。しかも、ヘルプの文言がどうしようもなかった。
(前略)
securesuitejp.net上にあるヘルプページ
Q11 「本人認証サービス」を利用したが、お店から別の方法で支払うように要請された(お店の画面に表示された)。
「パスワード入力画面」で[キャンセル]ボタンをクリックした場合に起こる可能性があります。もし、UFJカードWebサービスのパスワードを忘れた場合は、お手数ですがUFJカードWebサービスへの再登録をお願いいたします。
UFJカードWebサービス新規登録はこちら : http://ufjcard.com/weblifeclub/ws.html
Q12 「本人認証サービス」を解除したい(利用したくない)のですが?
UFJカードWebサービスへログイン後、「本人認証サービス(安全なオンラインショッピングをサポート)」メニューにて登録を解除いただけます。
UFJカードWebサービスのURLはこちら : http://ufjcard.com/weblifeclub/ws.html
うーん呆れる。しかも http://ufjcard.com/weblifeclub/ws.html などというページは存在しなかった。
追記1: securesuitejp.net の expiry は次のようになってました。6/28ってもうすぐですね。
Record expires on 28-Jun-2007. Record created on 28-Jun-2002.
追記1に追記: 21-Jun-2007 にアップデートされていました。おいおい、担当者大丈夫か? 現時点での expiry は
Record expires on 28-Jun-2008. Record created on 28-Jun-2002.
となっている。
追記2: 結局のところさまざまな問題点があるのだが、ざっと考えて致命的なのは以下だろう。
- 何のために必要なサービスなのかがユーザに明示されていない。
- ユーザが望めば利用しなくてもよいサービスであることが、サービス提供者からユーザに明示されていない。
- securesuitejp.net 上で提供されるインターフェイスは、カード会社のものではなく、カード会社にシステムの一部を提供する組織のものであることが明示されていない。むしろ、「カード会社のもの」であると偽っている説明がある。
- 正式なサービス名がユーザに伝わっていない (「3Dセキュア認証」「3-D Secure™」「本人認証サービス」etc.)
- コモンシークレットが意味を成していない。サービスの利用前にコモンシークレットの設定を義務付ければいいのか?そういうものでもないだろう *2。
シリアルポートを UNIX ドメインソケットに見立てる
追記: socat で stdio を指定すればいいような気がしてきた。
VMWare には、ゲストOSのシリアルポートを、ホストOSの UNIX ドメインソケットに見立てる機能がある *1。これを有効に活用するためには、現在使用している端末とそのソケットをつなぐプロキシがあればいいのだけど、ちょっと探した限りそのような要求を満たすものが見つからなかったのでざっくり書いてみたのが次の Ruby スクリプト。ツッコミどころ満載な気がするけども、何かの役に立つことを願いつつ。
端末には VT220 互換のものを想定している。F12 を押すとプロキシを終了する。使用するときは sockaddr_un('/tmp/aho') の /tmp/aho を、VMWare のソケットへのパス名に変えてください。
追記: そういえばこのままだとエスケープキー効かなくなるということに後で気づいた。そのうち直す。
追記2: ESC がバッファの最後の文字でなければエスケープシーケンスだとみなすようにしてみた。とりあえずはこれでおk。
require 'socket' require 'termios' ci = IO.open(0) co = IO.open(1) orig_term_state = Termios.tcgetattr(ci); term_state = orig_term_state.clone() term_state.lflag &= ~(Termios::ISIG | Termios::ECHO | Termios::ICANON) Termios.tcsetattr(ci, Termios::TCSANOW, term_state) s = Socket.open(Socket::PF_UNIX, Socket::SOCK_STREAM, 0) s.connect(Socket.sockaddr_un('/tmp/aho')) outbuf = '' inbuf = '' escbuf = '' state = 0 running = true while running r = IO.select([ci,s],[co,s],nil,1) if r[0].include?(s) inbuf += s.sysread(16384) end if r[1].include?(co) and not inbuf.empty? co.syswrite(inbuf) inbuf = '' end if r[0].include?(ci) buf = ci.sysread(16384) p = 0 while p < buf.length case state when 0 i = buf.index(0x1b, p) if i != nil and i != buf.length - 1 outbuf += buf[p...i] p = i esc_buf = '' state = 1 else outbuf += buf[p..-1] p = buf.length end when 1 if esc_buf.length < 5 c = buf.length - p c = 5 - esc_buf.length if c > 5 - esc_buf.length esc_buf += buf[p, c] p += c end if esc_buf.length >= 5 case esc_buf when "\x1b[24~": # VT220 F12 running = false end state = 0 end end end end if r[1].include?(s) and not outbuf.empty? s.syswrite(outbuf) outbuf = '' end end Termios.tcsetattr(ci, Termios::TCSANOW, orig_term_state)