前へ << ヘッダ | CGI のセキュリティ >> 次へ |
CGI プログラムを配布しているサイトの説明書には、 「パーミッションは 755 で」とか「700」で、などと書かれています。 この意味はしかし、実際はサーバごとに設定すべきパーミッションは異なります。 具体的には「CGI の実行権限」によって違うわけです。 大まかにわけて、CGI の実行権限には 2通りのポリシーがあります。
1 の場合は、http://X68000.q-e-d.net/、 http://X68000.q-e-d.net/~68user/、 http://X68000.q-e-d.net/~hogehoge/ など いずれの URL にアクセスしても nobody というユーザの権限で動きます。 一方、2 の場合は
- nobody 権限で動かすべし
- 各ユーザの権限で動かすべし
で動きます。
- http://X68000.q-e-d.net/~68user/ 以下にアクセスした場合は ユーザ 68user の権限
- http://X68000.q-e-d.net/~hogehoge/ 以下にアクセスした場合は ユーザ hogehoge の権限
これは、どちらが正しいという問題ではありません。 例えば大学などでは、各ユーザはメールを読み、プログラムを書き、 レポートを書き、研究成果を書きます。これらのファイルは 各ユーザの権限で置かれています。
もし 2 のように WWW サーバを各ユーザの権限で動かすと、 WWW サーバにバグがあったり CGI プログラムにセキュリティホールがあった場合は、 メールやレポートが外部から読まれたり消去されてしまう可能性があります。 このような場合は nobody 権限で動かすのが適当です。
しかし、一般のプロバイダのような web を公開するだけのサーバでは、 web 以外のファイルは存在しません。 つまりメールなどのような守るべきデータは存在しません。 というより、web コンテンツこそが守るべきデータであると言った方がよいでしょうか。 こういう場合は 各ユーザの権限で実行する方がいいでしょう。
自分のサーバでは、CGI が nobody 権限で動いているのか、 あるいは各ユーザ権限で動いているのかを確かめましょう。1: #!/usr/local/bin/perl 2: 3: print "Content-type: text/plain\n\n"; 4: printf "I am %s.\n",(getpwuid($>))[0];このスクリプトを設置し、実行します。 このサーバ (X68000.q-e-d.net) では、CGI は nobody 権限で動いていますので、I am nobody.と表示されます。「I am www.」となるサーバもあるでしょうが、 これも nobody と同じく、どのユーザでも www の権限で動くということです。もし、各ユーザの権限で動いているならば、「I am 68user.」のように、 自分のユーザ名と同じ表示になるはずです。
CGI・SSI を各ユーザの権限で動かしたいなら、 suExec か cgiwrap をインストールして下さい。 ただし、このインストールは管理者しかできません。
「うちのサーバはnobody 権限で動く。でも何とかして自分の権限で CGI を動かしたい」 という人もいるでしょう。 そういう場合は、suid という仕組みを使います。まずは UNIX の部屋: setuid をよく読んで下さい。理解したら、
1: #!/usr/local/bin/perl 2: 3: print "Content-type: text/plain\n\n"; 4: printf "I am %s.\n",(getpwuid($>))[0];を実行してみて下さい。このスクリプトの内容は whoami.cgi と全く変わりません。しかし「I am 68user.」と 所有者権限で動いていることがわかるでしょう。その理由は (言うまでもありませんが) setuid です。 whoami-suidperl.cgi のパーミッションは 4755 になっています。 perl スクリプトのパーミッションを 4755 にするだけで
という流れになり、めでたく所有者権限で動作します。
- WWW サーバ (httpd。このときはまだ nobody権限) が、whoami-suidperl.cgi を実行
- カーネルが先頭行の #!/usr/local/bin/perl を見て、 /usr/local/bin/perl whoami-suidperl.cgi を実行
- /usr/local/bin/perl が whoami-suidperl.cgi のパーミッションをチェック
- 4755 なので /usr/local/bin/suidperl whoami-suidperl.cgi を実行
- /usr/local/bin/suidperl は root に suid されているので、実行権限を スクリプト所有者の権限に設定し、whoami-suidperl.cgi を実行
なお、スクリプトなのに suid が効くのは、perl と suidperl が気をきかせてくれるからです。sh スクリプトや csh スクリプトではできません。
1: #include <stdio.h> 2: #include <unistd.h> 3: #include <sys/types.h> 4: #include <pwd.h> 5: 6: main(){ 7: struct passwd *pw; 8: uid_t euid; 9: char *home_dir; 10: char target[128]; 11: int len; 12: 13: euid = geteuid(); /* 実効 UID を取得 */ 14: pw = getpwuid(euid); /* 実効 UID のホームディレクトリを取得 */ 15: if ( pw == NULL ){ 16: fprintf(stderr,"Can't get home directory.\n"); 17: return 1; 18: } 19: 20: home_dir = pw->pw_dir; 21: 22: /* /home/foo/public_html/webcgi/sample/perl/whoami.pl を target に */ 23: len = snprintf(target,sizeof(target),"%s/public_html/webcgi/sample/perl/whoami.pl", home_dir); 24: 25: 26: if ( len >= sizeof(target) ){ /* バッファが小さすぎる */ 27: fprintf(stderr,"Buffer is too short.\n"); 28: return 1; 29: } 30: 31: execl(target,target,NULL); /* 実行 */ 32: 33: /* exec からは戻ってこないはずなのに…エラー */ 34: fprintf(stderr,"Can't exec %s\n",target); 35: return 1; 36: }
前へ << ヘッダ | CGI のセキュリティ >> 次へ |