HTMLのテキストやCGIファイルはそのpermissionをotherに対して適切に
公開しておく必要がありました。なぜなら HTTPdがそれらのファイルに
アクセスするときに一般に他人としてアクセスするからです。
Web server を起動する人は rootですが、web serverは rootとしては
振舞わず、nobodyとして振舞います。nobodyのIDは標準として
UID=65534であり、GID=65534のnogroupに所属しています。それゆえ
ページはpermissionはotherに対して公開されていないとならないのです。
HTMLやCGIを他人が見たり実行できたりするようにすることには なんらためらいはないでしょう。見せるために作るのですから。
しかし、CGIにファイル書き込むを行わせると困ったことになります。 Otherも書き込みできるように permission を他人に開かなくては ならないのです。こうすると、他人がUNIX directoryを辿って、 そのファイルにいたずら書きをすることができてしまいます。
CGIが新規ファイルを作成するようになるともっと困ったことになります。 新規ファイルを作るには、その親directoryへの書き込みが 必要になります。しかし、これを開くと悪意を持った人がその下の ファイルすべてを削除することができるようになってしまいます。 ファイルの存在は親directoryによって保証されているからです。 directoryの書き込みpermissionを開くことは非常に危険なのです。
FORMから閲覧者に書き込んでもらったデータはファイルに残しておきたい のは当然なのですが、それをするためには非常に危険なファイル環境に なってしまうのです。そこでそのような危険を避けるうまい手が用意されています。 通称 Sbit もしくは set-user-ID と呼ばれる技術です。 もうひとつ、web server の機能として SuExec と呼ばれる機能を server 管理者が設定する方法があります。SuExecについては 本章末で解説します。
UNIXのログイン名にはそれに対応して uid(User IDentifier)と呼ばれる数字 が存在します。idコマンドを実行すると自分や他人の uid 等を確認することができます。 uidはファイルの所有者の識別やプロセスの実行者の識別にも使われている UNIXの permission を管理する大事な数字なのです。
プログラムを実行すると、その実行者の uid が process user id として設定されます。この process uid には2種類のIDがあります。
Real User ID ( 実ユーザID )通常は両方とも同じ値であり、プロセスの実行者の uid の値です。 プロセスがファイルにアクセスする際には、そのファイルの所有者の uid とそのファイルの permission と プロセスの Effective User ID の値を 考慮して、そのプロセスによるファイルアクセスの許可不許可を判断します。
Effective User ID ( 実効ユーザーID )
Real User ID はプロセス実行中に変わることはありませんが Effective User ID はある条件下で変更することができます。
Effective User ID を変更するための条件として、
その実行ファイルの属性のひとつである set-user-ID-bit が
立っていることが必要です。これを立たせるためには次のようにします。
ls -l exefile として permission を確認してください。chmod u+s exefile
Userの領域の x が s に変わっています。この変更作業を Sbit を立てる とも言います。S bit が立っているファイルを実行すると Process User ID は次のようになります。-rws--x--x 1 naoki 24576 Sep 11 11:51 exefile
Real User ID は実行者の User ID になる。。permission において調べられる Process User ID は Effective の方です。他人がこのプログラムを実行すると、Effective User IDが その所有者と同じになるので、その所有者しか読み書きできない ファイルにも読み書きできるようになるのです。つまり 実行ファイル所有者と全く同じ権限を使えるのです。
Effective User ID は所有者の User ID になる。
Effective User ID をプロセスの途中から変更することができます。 ただし、変更できる値は、実行プログラムの所有者の uid か実行者の uid のみです。
変更する命令はC言語では
int seteuid( int new_euid );です。引き数に新しいIDをいれます。返値は新しく設定されたIDです。 設定に失敗すると-1が返ります。
関連する関数も紹介します。
int geteuid( void );Effective User ID を返します。最後のsetuidが使えるのは Supper User のみです。
int getuid( void ); Real User ID を返します。
int setuid( int new_ruid ); Real User ID を変更します。
Sbitを立てた実行プログラムは他人が自分に化けることを許すものです。 そのことは非常に恐ろしいことにも思えます。しかしながら うまくこの仕組みを利用することで逆に非常に安全な環境を作ることができるのです。
Sbitが立ったCGIをHTTPdが実行すると、そのプロセスの real uid は nobody のuidで effective uid はCGI所有者、つまり自分のuid になります。 このプロセスによるファイルの読み書きの際のpermissionの検査はすべて 自分のuidを用いて行われます。つまり自分の権限でファイルの読み書きが行われます。 自分のディレクトリに自分のプロセスがファイルを作るのは自由ですし 自分のプロセスだけが読み書きするファイルは他人に見えなくても構わないです。 こうしてデータファイルやディレクトリを他人に対して完全に閉じることができます。 他人はこのCGIを通じてのみ、それらのデータファイルにアクセスすることになります。 このCGIは自分が指定する動作のみを行うのですから、 自分の権限をこれ以外の目的に使われることはありません。 もちろんプログラムに security holeがあると想定外の動作をしてしまいますが。 Nobodyが自分になっているというのは気持ちの良い事ではありません。 通常は Effective User ID を nobodyのIDにしておいて ファイルを open するときにだけ所有者のIDにしてopen したらすぐ nobodyのIDに変えるのが衛生的です。
例を示しておきましょう。
#define NOBODY 65534 // nobodyのUserID は 65534 #define OWNER 9952 // 自分のUserID。各自調べること。 int main( void ) { seteuid(NOBODY); // プログラムの最初の最初でNobodyに戻しておく。 /* * いろいろな作業をする。 */ seteuid(OWNER); // ファイルを開ける直前で自分に化ける。 FILE* stream = fopen("article.txt","w"); seteuid(NOBODY); // ファイルを開けたらすぐにNobodyに戻る。 fprintf( stream,"hello, world!\n"); // 何か読み書きをする。 fclose( stream ); // 閉じる。 }
Sbitが立ったプログラムがメールを送信すると メールの差出人はプログラムの所有者になります。 CGIでメールを送ると差出人が nobody の気味の悪いメールになりますが Sbitを立てておけば自分のメールになります。
Apacheでは、SuExecと呼ばれる機能を利用することができます。 ただし標準ではこの機能が使えないようになっていて、管理者の判断で この機能が有効になるように設定することができます。
SuExecが有効になっていると、すべてのCGIは所有者の権限で実行されます。 Sbitが立っていることと似ていますが、逆にnobodyになれません。 なので CGIによるファイルの読み、書き、新設、削除のどれでも、 ファイルや親directoryのpermissionは他者に対して完全に閉じていても 構いません。自分ができることは他人もできるというわけです。 気をつけて下さい。この場合にドジなCGIを作るとあなたにとって致命的な セキュリュティーホールとなります。詳しくは解説しません。むしろ 被害の可能性を予測できない人はCGIを作ってはいけません。