68user's page 掲示板

Prev< No. 229〜247> Next  [最新発言に戻る] [過去ログ一覧]
No. 229 # M.Masuda 1999/03/26 (金) 01:33
なぜじゃ〜どうしてじゃ〜←狭間かんぺい調(爆)
>一般ユーザで...

これもだめです。68Userさんが前に書いたとおりアクセス件が無いと
怒られます。
Insecure $ENV{PATH} while running setuid at ./su.cgi line 13.
と出ました。

>httpdのエラーログに、PATHがどうこう、と...
アパッチのerror_logは、だんまりです。(>_<)

>ここらへんがくさいです。
これも68Userさんと同じコードで試しました、がダメ。

ひとつ不思議を見つけました。
perl -c とすると、Args must match #! line at su.cgi line 1.
と出ます。

んっ!

とここまで書いて、他の事をいろいろ調べたらどうもこれが
前に疑問だった、suExecの機能のようです。
http://japache.infoscience.co.jp/japanese/manual/suexec.html
ってことは、68Userさんの環境はsuExecが実装された環境のようで
すね。
#今夜はずっとこの問題で格闘していたのでつかれた....ふげっ!

aliasの件は、ダミーユーザー(ログオンしない)宛のメールを管理
者に転送するという意味です。
#やってみれば分かりますね...(^^;
.bashrc等の設定ファイルに記述するのは、普通コマンドのailas
なのですか?

#なんかドッとつかれた....(T_T)

No. 230 # 68user 1999/03/26 (金) 02:20
うちでは #!/usr/local/bin/suidperl でも動きました。

> perl -c とすると、Args must match #! line at su.cgi line 1. と出ます。
suidスクリプトの実行時には、perlに渡す引数と
suidperlに渡す引数が同じでなくてはいけません。
# …と、青ラクダ本に書いてありました。

> これも68Userさんと同じコードで試しました、がダメ。
/usr/bin/perl は perl5 ですか?

FreeBSDの場合、FreeBSD 3.0R から /usr/bin/perl が perl5 に
なったのですが(それまではperl4)、その /usr/bin/perl は
suidperl が起動しないようになっていると聞きます。Linuxでも
OSの方針で、suidperlを実行しないようにコンパイルされている
のかもしれません。

> 68Userさんの環境はsuExecが実装された環境のようですね。
いえ、うちにはSuExecは入れてません。

何か問題が発生すると原因を切りわけていく必要があります。
httpdが原因かもしれないので、CGI経由で実行するより
コマンドラインで実行すべきかと思います。


> aliasの件は、ダミーユーザー(ログオンしない)宛のメールを管理
> 者に転送するという意味です。
ん〜、まだちょっと意味がわかりかねます。

> .bashrc等の設定ファイルに記述するのは、普通コマンドのailas
> なのですか?
そうです。コマンドの alias と /etc/aliases は全く別物です。

ROLさん
> ついにLinux起動いたしました(笑)
FreeBSDじゃないんですねぇ(^^;

> しかし、ここの話題についていけるようになるのに、どれだけの時間がかかるやら…(笑)
やる気があればすぐですよん。

No. 231 # 68user 1999/03/26 (金) 03:12
え〜、FreeBSDでは、gethostby* は libc に入ってますので、
gethostbyaddr のソースは
    http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/net/gethostnamadr.c?rev=1.10.2.1
ここらへんです。/etc/hostsなどを見て、見付からなかったらDNS引きに
いきますが、それを担当するのは
    http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/net/gethostnamadr.c?rev=1.10.2.1

    struct hostent * _gethostbydnsname(addr, len, af)
あたりでしょうか。で、そこらへんの絡みで、
    static struct hostent * gethostanswer(answer, anslen, qname, qtype)
が呼ばれますが、そこで
    host.h_aliases = host_aliases;
    host.h_addr_list = h_addr_ptrs;
といったことをしています。で、host_aliases や h_addr_ptrs は
gethostnamaddr.cの先頭で
    static char *h_addr_ptrs[MAXADDRS + 1];
    static struct hostent host;
    static char *host_aliases[MAXALIASES];
    static char hostbuf[8*1024];
などと定義されいます。ちなみに
    #define MAXALIASES 35
    #define MAXADDRS 35
です。

> これらがすべて静的領域に確保されているとは考え難いと思います。
というわけで、全て static で宣言されているようですね。当然ですが
    if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
        if (!toobig++)
            dprintf("Too many addresses (%d)\n",MAXADDRS);
エラーチェックもしています。

> 先日某所で尋ねられた件について、ちょっと分からなかったので、
> 質問させて下さい。
もしよろしければ、その話題が出たのはどこなのか教えていただけますか?
こういう楽しい話題が出るところに参加したいもので。

No. 232 # 68user 1999/03/26 (金) 13:03
> いきますが、それを担当するのは
>  http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/net/gethostnamadr.c?rev=1.10.2.1
失礼、
    http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/net/gethostbydns.c?rev=1.23
こっちでした。

でも、char **である host_aliases や h_addr_ptrs が指している
char * な領域ってのはどこかな? よく読んでませんが、
    static char hostbuf[8*1024];
っぽいですね。

No. 233 # mm 1999/03/26 (金) 22:06
>はい、勝手にfreeしてくれます。
なるほどー!
freeしなかったリスクは、ユーザーだけが引き受けて、
他人に迷惑を掛けるおそれはない訳ですね。

マルチユーザーのメモリ管理をちゃんと勉強しないといけないなぁ…


>え〜、FreeBSDでは、gethostby* は libc に入ってますので、
>gethostbyaddr のソースは
あっ、すいません。先に教えて頂いたときに、いろいろあるなー
と感心してたのですが、ライブラリのソースがあることまでは、
考えが及びませんでした(^^;;;
MS-DOSでも、入手可能な場合はありますが、有償だったり…
うーん、やはり羨ましい世界だぁ…

ともかく、詳細な解説ありがとうございましたm(_ _)m

>というわけで、全て static で宣言されているようですね。
ガ〜ン!
こういうコーディングもありなのかぁ…
16bitアドレス(MS-DOSのnearポインタ)でアクセスできる
最大64KBのデータ領域に慣れてしまうと、8KBもの静的領域
ってのが発想しづらい…(^^;

>char * な領域ってのはどこかな? よく読んでませんが、
> static char hostbuf[8*1024];
>っぽいですね。
ですね。hostbufのh_nameの後に順に書き並べて、このアドレスを
h_aliases[]にストアしてるみたいです。


>もしよろしければ、その話題が出たのはどこなのか教えていただけますか?
残念ながらプログラミング関連のボードではないので、
ご期待には沿えないかもしれません(^^;
それと、一応隠しボードなので、ここには書けないです。
でも、リンクを逆に辿って来るのはOKって言ってたので、
向こうからこっちにリンクを張っておきますんで、
覗いてみて下さい(笑い)

No. 234 # M.Masuda 1999/03/27 (土) 16:35
ふぅ、この前はつかれてたのでなかば強制的に自分なりの解答と
してしまいましたが、引き続き調べてみました。
#くっそー、グヤジイ!!!(怒笑)

>/usr/bin/perl は perl5 ですか?
This is perl, version 5.004と(TurboLinix)
This is perl, version 5.004_04 built for i386-linux(RedHat)です。

> perl -c とすると、Args must match #! line at su.cgi line 1.
コマンドラインでいくつかのパターンを試しましたが、ラクダ本のP644では
>あなたが指定したものは、あなたが考えたようには解釈されない可能性がある。
という意味らしいです。
#このシステムではサポートされないという意味なのかなぁ。

だけどrootのコマンドラインからでは全く問題無く動きます。

ちなみに、一般権限でコマンド上の実行は、スクリプトの内容通り
cat /etc/ftpaccess でエラー終了します。
その際のメッセージです。
Insecure $ENV{PATH} while running setuid at ./su.cgi line 15.
#当然の結果ですよね。

> suidスクリプトの実行時には、perlに渡す引数と
> suidperlに渡す引数が同じでなくてはいけません。
「青ラクダ本に書いて...」すいませんページ教えてくれません
か。m(_ _)m

>何か問題が発生すると原因を切りわけていく必要があります。
> httpdが原因かもしれないので、CGI経由で実行するより
> コマンドラインで実行すべきかと思います。
コマンドラインでは、68Userさんの言う通りの結果だったので
やはりhttpdの方なんでしょうか。


>そうです。コマンドの alias と /etc/aliases は全く別物です。
アッそうか!
完全に勘違いしていました。(>_<)

で、/etc/aliasesを修正し newaliasを実行したのですが...
反映されませんでした。

FreeBSDだと、/etc/aliasesを修正して、newalisasを実行するだけで
反映されるのでしょうか?

現在英語マニュアルと格闘中です。
ちなみにnewalias事項の際に、以下のようなメッセージが出ます。
Couldn't open /usr/lib/aliases.text for input!
#どうも/usr/lib/aliases.textが開けないと言っているらしい。

#英語圏で生まれていれば、こんな苦労は無かったのに(; ;)

No. 235 # M.Masuda 1999/03/27 (土) 16:37
追加ですが。
> perl -c とすると、Args must match #! line at su.cgi line 1.
これは、スクリプトのパーミッションを4755とした時にでます。
0755にすると出ません。
なにか関係があるのでしょうか?

No. 236 # 68user 1999/03/27 (土) 20:45
> ちなみに、一般権限でコマンド上の実行は、スクリプトの内容通り
> cat /etc/ftpaccess でエラー終了します。
    #!/usr/local/bin/perl
    $ENV{PATH}='';
    open(IN,"/etc/ftpaccess");
    print <IN>;
ではどうですか? これでダメなら、suidperlは使えない設定になっている
んじゃないでしょうか。

> すいませんページ教えてくれませんか。
    > ラクダ本のP644では
    >>あなたが指定したものは、あなたが考えたようには解釈されない可能性がある。
    > という意味らしいです。
の6行下に書いてあります(^^; M.Masudaさんが見てるのは違うメッセージの
説明ですよね。

> FreeBSDだと、/etc/aliasesを修正して、newalisasを実行するだけで
> 反映されるのでしょうか?
はい、そうです。

> ちなみにnewalias事項の際に、以下のようなメッセージが出ます。
> Couldn't open /usr/lib/aliases.text for input!
FreeBSDでは /usr/lib/aliases.txt というファイルはないので
ちょっとわかりません。newaliases(1)、aliases(5)あたりに書いて
ありませんか?

バイト行くんで、この辺で。では〜。

No. 237 # M.Masuda 1999/03/28 (日) 00:25
バイトお疲れ様でした。

いや〜ハマリまくりです。(^^;
結果から言えば動きました。ありがとうございました。
#68Userさんの助言が無ければ、解明する前に諦めていました。

実験で分かった事です。
いくつかの要因が有りました、私のスクリプトがおかしかったの
ですが一番まずかったのは、一番最初に68Userさんの提示されたコー
ドの通りで動かなかったので、試験スクリプトはsystem()や`コマンド`
としていたのがいけなかったです。

つまり68Userさんのいうとおり、suidビットを立てると、あくまで
perlが行う操作(openとか)はsuid権限で動きますが、forkされた
プロセスでは、再びnobodyに戻ってしまう事です。
てっきりsuidの権限が継承されると思ってました。
#ちなみに $ENV{PATH}='';は削除しても動きました。

以下は試験に使用したスクリプトです。
生成されたファイルのオーナーを見てfork時の権限が分かりました。
#!/usr/local/bin/perl -w

$|=1;
print "Content-type: text/html\n\n";
print "<html><H3>suid</H3><pre>";

print "<hr>\n";

#$ENV{PATH}='';
open(IN,"./himitu.txt") || die "error:$!";
print <IN>;
close(IN);


open(OUT,">./make_open") || die "error:OUT $!";
print OUT "Open Command\n" ;
close(OUT);


if (!system("ls>make_system")) { print "Not Exec System $!\n"; }
print "Next Step OK!\n";

print "<hr>\n";
print "Script END\n";

print "</pre></hr></html>\n";


それと検証不足かも知れませんが、perlスクリプト内でsystemコマ
ンドを使うと、スクリプトが終了します。
上記の例でいうと、最後の方のprintが実行されません。
ファイルオーナーを、nobodyの時webから実行すると最後まで表示され
たので、もしかしたらセキュリティー面での仕様かも知れません。
#エラー位出してくれればいいのに。

それからどういう訳か、perlスクリプト内で closeとするとSTDOUT
までcloseしてくれちゃいます。#これってバグ?
おかげで勝手にスクリプトが終了するので、これが分かるまで苦労
しました。
#closeにハンドル名をちゃんと指定するとOKでした。

とりあえずこんなとこまで分かりました。
設定は面倒ですが、これでやりたかった事に見通しが出てきました。
ありがとうございます。

>の6行下に書いてあります(^^; M.Masudaさんが見てるのは違うメッセージの
> 説明ですよね。
お恥ずかしいばかりです。(>_<)


aliasesの方は、どこの解説も68Userさんと同じ説明でした。
他のパッケージのサーバーで試してみます。

PS
メール見てもらえましたか?

PS2
私の隠しブックマーク見ましたね(^^;

No. 238 # 68user 1999/03/28 (日) 09:03
> メール見てもらえましたか?
(僕にとっては)内容的に問題ないので、メールの続きはこちらでやります。

> その前に、田中 健という人物をご存知ですか?
> http://www.club.kyutech.ac.jp/~hermit/
いやぁ、知らないです。イントラネット内(インターネットとは繋がって
いない)で うちのページをコピーして社員向けに公開してもいいか、という
メールは頂いたことがありますけど、それとは多分違う人だと思います。

ま、別にいいですけどね。どうせ間違いだらけ/役に立たないコンテンツ
なので気にしません。おもしろいものを教えてくださって どうも
ありがとうございました(笑)

> forkされたプロセスでは、再びnobodyに戻ってしまう事です。
ん〜どうかなぁ? もしそうだとすると suidperl 内では、system や `` などで
サブプロセスを(所有者権限で)使えないことになりますが、だとしたら suidperl
の意味は半減しますよね。今 実行環境がないので、後からもう少し調べてみます。

> 私の隠しブックマーク見ましたね(^^;
ははは、見たかもしれません。

カウンタのあるページは referer 取ってますので、ご注意を>All
たまに、どんな風に紹介されてるか見に行ったりします。一度referer
たどって行ったらボロクソにけなされてて、喜んでそこの人にメール
書いたこともあります。
# だって、「いいページだ」と書かれるより、「ひどいページだ」と
# 書いてある方がうれしいから。悔しいので、ページを よりよいものに
# しよう、という気が起こりますよね。

このBBSは referer 取ってませんでしたが、mmさんに
> 向こうからこっちにリンクを張っておきますんで、
> 覗いてみて下さい(笑い)
と言われたので、昨日から取り始めました(^^; でも、それらしいものが
見付からないなぁ。

> あっ、すいません。先に教えて頂いたときに、いろいろあるなー
> と感心してたのですが、ライブラリのソースがあることまでは、
> 考えが及びませんでした(^^;;;
まぁ僕はローカルにソースを展開しているので、grep 一発で探せますが、
ネット上で公開されてても探すのはつらいですね。

No. 239 # 68user 1999/03/29 (月) 13:46
> forkされたプロセスでは、再びnobodyに戻ってしまう事です。
やはりうちではそうはなりませんでした。
    #!/usr/local/bin/perl
    $|=1;
    $ENV{PATH}="";
    print "Content-type: text/plain\n\n";
    open(IN,"/bin/cat /etc/master.passwd");
    print <IN>;
    if ( fork ){
        system("/usr/bin/id");
    } else {
        system("/usr/bin/id");
    }
というスクリプトをowner=root、permission=4755にして、コマンドライン、
httpd 経由両方で動くことを確認しました。600な/etc/master.passwdの
中身は表示されましたし、idの結果は
    uid=65534(nobody) euid=0(root)
となりました。forkしても実効ユーザはrootのままでした(まぁ system を
実行するってことは、fork/execしてるわけですが)。

なお、PATHをクリアしないと
    Insecure $ENV{PATH} while running setuid at ./hoge.cgi line xx.
となりました。

あ、ファイルを作成してみるのを忘れてた。もしかしたらそのとき作成した
ファイルのオーナーは実効ユーザIDでなく、実ユーザIDが使われるのかも
しれません。

No. 240 # M.Masuda 1999/03/29 (月) 15:19
えぇぇぇぇぇぇぇぇ!!!!!!???????
なんでぇ???
#すいません無駄な行を書いてしましました。(^^ゞ

なんか、うちの環境system関数が変です。
suidを立てずに、普通に755のパーミッションです。

#!/usr/bin/perl
print "Content-type: text/plain\n\n";

print "Script Start\n";

if(system("")){
                print "Done..\n";
}else{
                print "NG! \n";
}

#system("ls -l 2>&1");

print "End Script\n";

2つめのsystem関数(system("ls -l 2>&1")の部分)を、コメントア
ウトした時としない時の結果の結果を教えてくれませんか?

うちの環境では、2つ目のsystemを有効にすると、サーバーエラー
になります。
コマンドラインから実行すると、正常なんですが...。
#なぜ????

No. 241 # 68user 1999/03/29 (月) 15:39
うちでも同じです。print文がバッファリングされた
状態でsystemの結果が先に表示されてるのでしょう。
先頭で $|=1 とすればいいでしょう。

httpdがログ(/var/log/httpd-error.logなど)に
    [Mon Mar 29 15:32:06 1999] [error] malformed header from script. Bad header=total 1406:
と吐いてくれるはずです。

No. 242 # M.Masuda 1999/03/29 (月) 15:59
>先頭で $|=1 とすればいいでしょう。
なるほど、これ($|=1)も関係あったんですね。
う〜ん、もっと詳しく検証せねば。

もうちょっと探ってみます。

No. 243 # 68user 1999/03/29 (月) 16:11
一般的には、以下のの方法でデバッグすると、大抵の場合解決すると思います。
    #!/usr/local/bin/perl
    $|=1;
    print "Content-type: text/plain\n\n";
    open(EXEC,"| .$ENV{PATH_INFO} 2>&1");
    while (<STDIN>){
        print EXEC;
    }
という内容の wrapper.cgi を作ってください。hoge.cgiの動作チェックをしたいなら
    /~user/cgi-bin/wrapper.cgi/hoge.cgi

    /~user/cgi-bin/wrapper.cgi/hoge.cgi?data

などというURLで実行してください。そしたら、
    - $|=1を付けないと Content-type より ls の結果が先に出力されてること
    - system や open(COMMAND,"command |") の中で
            cat: /etc/master.passwd: Permission denied
        などのエラーが起こっていること

がわかるでしょう。一連の環境変数(QUERY_STRINGなど)は引き継がれますし、
POSTの場合のデータの受け渡しもできます。

というわけで、CGIが動かなかったら、まずはこれでチェックして
みてください。

あと
> もしかしたらそのとき作成したファイルのオーナーは実効ユーザIDでなく、
> 実ユーザIDが使われるのかもしれません。
は、suidなperlスクリプト中で新規ファイルを作成した場合は
perlスクリプト所有者権限で動きました。つまり
    uid=65534(nobody) euid=0(root)
の場合、新規ファイルのオーナーはrootになりました。

No. 244 # M.Masuda 1999/03/29 (月) 18:09
大変お騒がせしている、M.Masudadです。
こんどこそやっと解決マークがつけられそうです。(^^ゞ

>なんか、うちの環境system関数が変です。
この件に関しては、原因はsystem関数実行時に、指定コマンドの
パスが通って無いのが原因と判明しました。
フルパス指定するとsystem関数はちゃんと動きました。
今までsystemでコマンドを使ったサーバーのnobodyにはたまたま
コマンドのパスが通っていただけみたいですね。
#いままでぜんぜん気が付かなかった....。
#なんか一人で大騒ぎしてますね。←私(>_<)

まとめるとsuidスクリプトを、実行したい権限のオーナーにして
chmod 4755 を設定。
$|=1; でバッファリングを止めて、systemで使うコマンドはフルパ
スで指定するか、パスをあらかじめ指定しておく。

closeはどうですか?、ファイルハンドルを指定しなくとも最後に
openしたハンドルのみクローズされると、思っていたのですが。
suidな時、STDOUTまでクローズされませんか?

$|=1; は、保険と考えて全てのperlスクリプトに入れた方が、悩む
回数が減りそうですね。
やはりperlもosと密接に関係しているのが改めて分かりました。
こういうケースは、UNIXのシステムを十分理解していないとデバック
しきれなかったかも知れないですね。

http://www.excel-net.co.jp/~masuda/su/
にある su.cgi に試験スクリプトを置きました。
これで見ると、だいぶ嘘ついてましたね。(^^ゞ
今までの件が判明しました。

実験に付き合ってもらってすいませんでした。
wrapper.cgiもありがとうございます。
非常に勉強になりました。m(_ _)m

ところで、wrapper.cgiでのurl指定方法のwrapper.cgi/hoge.cgi
は、知ってはいたのですがどういう動作になるのですか?

># だって、「いいページだ」と書かれるより、「ひどいページだ」と
># 書いてある方がうれしいから。悔しいので、ページを よりよいものに
># しよう、という気が起こりますよね。
いや〜こういう前向きな考え方をできる人って、今時なかなかいな
いですよ。
#68UserさんってもしかしてA型?

No. 245 # 68user 1999/03/29 (月) 20:44
> ファイルハンドルを指定しなくとも最後に openしたハンドルのみ
> クローズされると、思っていたのですが。suidな時、STDOUTまで
> クローズされませんか?
suidかどうか/httpd経由かコマンドラインか に関わらず、STDOUTが
クローズされました。そもそもcloseってファイルハンドルを省略
すべきでないし、仮に省略した場合はselectで指定されたファイル
ハンドル(デフォルトはSTDOUT)がクローズされるんじゃないですかね?
# perl4、perl5.004で試しました。

> ところで、wrapper.cgiでのurl指定方法のwrapper.cgi/hoge.cgi
> は、知ってはいたのですがどういう動作になるのですか?
print文を埋め込んで試してみませう ;-)

No. 246 # M.Masuda 1999/03/29 (月) 23:01
>suidな時、STDOUTまでクローズされませんか?
ホントだぁ...これまた私の勘違い。
いままで作ったスクリプトを見直したら、ちゃんとやってました。
意識していたわけではなく、性格的な問題?からそうしていたの
ですが、これって案外重要だったのですね。
この件でのスクリプトでの試験では、安易にそうしていただけでし
た。#お恥ずかしい。(*^_^*;;;

closeのみだとSTDOUTまでクローズされ、結果スクリプトが終了して
しまうのですね。

>パスが通って無いのが原因と判明しました。
よく考えたら、スクリプト内で$ENV{PATH}=''としてるのに、何を
言ってるんでしょう私は。(; ;)
でもなんで、$ENV{PATH}=''としなければいけないのでしょうか。
新たな疑問!
#まるで小学生のガキが、なぜなぜ攻撃してるみたいですが..(^^ゞ
#最近、私を含め周りにUNIX信者が増えている模様です。
#だって面白いんだもん。

>print文を埋め込んで試してみませう ;-)
すいません、オバカでよく分からないのですが具体的にどうすれば
私にも理解できるでしょうか。
↑完全に開きなおってるかもしれない(^_^)V

これだけいろいろ御世話になっているので、何かお礼がしたいとこ
ろですが、なにか出来る事が有れば言って下さい。
と、いっても何が出来るわけでは無いし....でも気持ちだけは有り
ます。(本気度=120%)

No. 247 # 68user 1999/03/30 (火) 04:14
> すいません、オバカでよく分からないのですが具体的にどうすれば
> 私にも理解できるでしょうか。
何を知りたいのかわからないので、全部は説明したくないです(結構な量になるので)。
何を知りたいのでしょうか? できれば
    open(EXEC,"| .$ENV{PATH_INFO} 2>&1");
というのを書いたのだから、「とりあえずPATH_INFOの値を見てみる」
くらいは試してください。

> でもなんで、$ENV{PATH}=''としなければいけないのでしょうか。
一言で言えば「汚れている」からです。消す必要はなくて、PATHを
再設定すればよかったですね。長くなるので青ラクダ本 P.409 参照。

別に質問するなってわけじゃないですけど、自分で調べる努力は必要です。
それでもわからなかったらどんどん質問すればいいですけど、その際でも
極限まで発生条件を切り詰めた上で、
    「何がわからないか」「どのような状況で調べたのか」
などを書かないと、結局 回答者側が苦労するハメになります。

Prev< No. 229〜247> Next  [最新発言に戻る] [過去ログ一覧]