第3回 制御して 防いでこその セッションだ - セキュリティ講座

PHPセキュリティ

がる先生のセキュリティ講座

Lecutures on PHP

第3回 制御して 防いでこその セッションだ (その1)

 このエントリーをはてなブックマークに追加

メンバー以外はご遠慮願いたいのですが…

Webサイトの性質にもよるのですが、ある程度限られた人にだけ見せたいといったサイトの要求は、決して少なくないものです。がる先生
例えば「会員制サイトを作りたい」という要望は、そこらのいわゆる案件系サイトとかをみれば容易に見つけることができます。

ただ、この「限定した人にだけ見せたい」という要望に対する実装手段には複数の手法があり、それらにはそれぞれに「知らないと危険な」注意点や問題点が、あるのです。

そうは言っても紙芝居…

まずはじめに知らなければならないのは「HTTP上で認証という状態を作り出すのはきわめて厄介である」という事実です。きょうびどこに行っても見る認証の技術が「実はHTTPというプロトコルと非常に相性の悪いものである」ことを、まずは説明いたしましょう。

本質的に、Hyper Text Transfer Protocolというのは「要求送って返事もらって終わり」の1往復完結主義です。

要求送って;
応答もらって;

の2行で終了してしまうものなのです。

けっして

do {
要求送って;
応答もらって;
} while(
終了フラグがたつまで);

ではありません(よく「紙芝居」とか言われる所以になります)。

認証というのは基本的に「一人のユーザの一連の操作の流れ」であると言い換えることが出来ます。今アクセスした人が一つ前にアクセスしたのはここで、もう一つ前はそこで…という「一連の情報」です。
しかし上述のような「紙芝居な仕組みであるHTTP」は、「一連の流れ」として把握するために必要なつながりを持っていないために、何の工夫もしないと「一連の流れ」というものについて「把握できない」ということになってしまいます。

つまり「認証状態が確保できない」ということになります。

もちろん上述を踏まえて「だからセッションとか認証とかは無理なんです」と言い切れれば、技術者的には楽だったのかもしれません。
しかし一般社会にWebが浸透するに従い、認証という要求は不可避なレベルにまで高まってきました。要求があれば供給をしていくのがビジネスってもんです。かくして、いくつかの手法が出てきました。

お手軽で…危険なBASIC認証

そこで出てきたものの一つがBASIC認証になります。BASIC認証の仕組みは比較的単純で、大抵のブラウザで処理可能なものでした。

ブラウザ(より正確にはクライアント)から要求があったときに、サーバプログラムはその要求をうけ、一旦401番というステータスでブラウザに返事を返します。がる先生
ステータスというのは、Webにおいては大抵3桁の、意味のある数字で、たとえば有名なところで「404 Not Found」や「500 Server Error」があるかと思いますが。

401番は「ここは認証が必要なPageだからIDとパスワードを要求する」という意味になります。この戻り値を受け取ったブラウザは「IDとパスワードの入力画面」を表示して、入力を促します。入力されたらもう一度、今度はIDとパスワード付きのリクエストをサーバに流し、サーバはそれを受け取って、IDとパスワードの組が正しければ、コンテンツを返します。

ちょっと文章だとわかりにくいですね。表にしてみましょう。

クライアント          サーバ
Page要求         →  要求を受け取る
401番を受信       ←  401番を返す
ID+パスワードを入力
ID+パスワード付要求    →  IDパスワード付き要求を受け取る
                IDとパスワードを確認する
コンテンツを受信、表示   ←  コンテンツを返す

こんな流れになります。

では、認証されている2Page目以降はどうなるのでしょうか?

クライアント          サーバ
Page要求         →  要求を受け取る
401番を受信       ←  401番を返す
"先ほどの入力値を覚えておいて"
ID+パスワード付要求    →  IDパスワード付き要求を受け取る
                IDとパスワードを確認する
コンテンツを受信、表示   ←  コンテンツを返す

こうなります。つまり、BASIC認証は「毎回IDとパスワードで認証をしている」やり方になります(言い方を変えると「毎回ログインしている」とみなすことも可能です)。
ちなみにこういったデータは「ヘッダ」という部分に記載されますが、それは以下のような書式になります。

Authorization: Basic 文字列

ちなみに上述の文字列は、以下のようなプログラムで作成されているものと等価です。

文字列 = base64_encode(ID . ':' . パスワード);

つまりBASIC認証は「パスワードとIDをBASE64でエンコードした」だけのものを、毎回通信パケットに乗せてやり取りしているのです。

もし「セキュリティ」を基準にBASIC認証を語るのであれば、その実装は、正直あまりにも「お粗末である」といわざるを得ません。ちなみにBASIC認証の上位としてDigest認証もあります。これはパラメタ部分である文字列を「MD5でhash化」しているものになります。

BASIC認証より多少はマシですが、やはりマシ以上のものではありません。

ここでワンポイント。がる先生

BASE64は、マルチバイト文字やバイナリなどのあらゆる情報を、64種類の印字可能な英数字のみを用いて扱うためのエンコード方式です。PHP的には、base64_encodebase64_decodeの関数を用いて、BASE64を取り扱うことが出来ます。
MD5は、入力に対して常に128ビットのハッシュ値を出力する、「ハッシュ関数」と呼称されるもののうちの一つです。PHP的にはmd5関数でハッシュ値を作成することが出来ます。

話を元に戻しまして。

使っちゃいけない………とはあえて、あえて、申しませんが、せめて熟考を重ねて欲しいのが「BASIC認証」「Digest認証」です。
内々用に簡易的にとりあえず、であればよいのですが、きちんとした会員サイトをBASIC認証やDigest認証で作成するのは、どんな理由があってもなお、まったくオススメできません。

問題点を整理してみましょう。

いくつもあるのですが、最大の難所は「IDとパスワードが毎回流れている」部分です。
したがって、この部分がどうにかヘッジできる手法であれば、少なくともBASIC認証やDigest認証よりはよい可能性が高い、と考えられます。

  • 1
  • 2

  



Pick Up Q&A

Q
PHPのHTML埋め込み記述について
 このエントリーをはてなブックマークに追加 
A
$_POST["data"] == "男" ? $val = "checked" : $val = "" ; の意味は以下と同じです。 if($_POST["data"] == "男"){ $val = "checked; } e...

>>続きを読む

kende様のご指摘通り、三項演算子を使用する際には、コードの複雑度などを考慮する必要がありますね。書きやすさと共に可読性も追求したいところですね。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)