perlでアップローダを作ったのですが、クラックを受けている様なんです。

./up の配下にしかアップロード出来ない様にしたつもりが、その上のディレクトリに.htaccessやらindex.htmやらを設置されて困っています。

ソース:
http://showizh.cool.ne.jp/cgitest/uploader.txt

ログが残る様にしたのですが、攻撃の際のログは記録されていません。(通常のアップに関してはちゃんと記録されます)
どこにセキュリティホールがあるんでしょうか?

サーバはレンタルのtok2proです。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2009/04/05 10:50:38
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答5件)

id:pahoo No.1

回答回数5960ベストアンサー獲得回数633

ポイント24pt

不正拡張子のチェック部分が間違っているように思います。下記のように修正してみてください。

foreach(split(/ /,$ngextentions)){
    if($name =~ /\.$_/){ print LOG "!!dangerfile!!\n";exit;}
}
id:neuromancer_sho

アンダーバーの後のダラーは文字列の最後という意味で合っていると思うのですが。

不正拡張子は(自分でテストし)ちゃんと検出され、ログに出力されています。

2009/04/01 21:42:29
id:pigment No.2

回答回数95ベストアンサー獲得回数2

ポイント4pt

setparaとかupfileという名前付けが気に入らない。ちゃんと英語にしてくれ、気持ち悪い

それとログに時刻その他が入ってないのもダメだろ

という諸々は置いといて、このCGI経由でなく置かれているんじゃなかろうか?

id:neuromancer_sho

ログに時刻 - たしかに。

CGI経由じゃない - そんな気もしますね。

2009/04/02 00:08:07
id:shintabo No.3

回答回数45ベストアンサー獲得回数10

ポイント24pt

# これはダイジョブですか?

if($ENV{'REQUEST_METHOD'} eq 'POST'){ &upfile; }

else {

&setpara;

# で、

sub setpara{

foreach my $pair (split(/&/ , $ENV{QUERY_STRING})){

chop;

my($sep1 , $sep2) = split(/=/ , $pair , 2);

$form{$sep1} = $sep2;

}

if($form{"createdirname"} ne ""){

mkdir $dir."/".$form{"createdirname"}, 0701;

&reload;

}

# が呼ばれてますが、GETリクエストで

createdirname=../../up2

# など入っていると、そのまま作ってしまいそうなのですが・・・

# また、chopもchompにしておかないと、末尾を削除しちゃわないですか?

# 次に

sub viewfile {

if($dir !~ /^\.\/up/ || $dir =~ /\.\./){ print "このフォルダは表示出来ません
";exit}

# ですが、上の例でいくと、

movetodir=./upupupupup

# で、GETリクエストがくると、そのまま通りそうです

# upfileメソッドも同様ですね

# あとは、

use strict;

# は、必ずつけましょーっていうのと、HTML::TemplateなどでMVCを分けたほうがよいのではないでしょうか?

id:neuromancer_sho

chop要らないですね。どこかからコピペしてきたのがそのまま残っていたようです。

・ディレクトリが意図しない場所に作られてしまう

・頭に"up"がついているディレクトリであればアップロード・表示可能

ということですね。しかし、迷惑ファイルが置かれる場所は ./up の真上のディレクトリ(頭に"up"はついていない)でした。

HTML:\:Templateというのは始めて知りました。

大変参考になりました。ありがとうございます。

あ、言い忘れました。perlのバージョンは5.0なのでJcode.pmを使っています。

2009/04/02 01:32:07
id:rryu No.4

回答回数30ベストアンサー獲得回数2

ポイント24pt

HTTPにはユーザーエージェントが受け取り可能なメディアタイプ・言語・エンコーディングを考慮して

適切なリソース(のバリアント)を返すコンテントネゴシエーションという機能があります。

Apacheでは、このバリアントを実現するのに追加の拡張子を付けたファイルを用意するという方法が取られています。

たとえばtest.htmlの日本語版ならtest.html.ja、

英語版ならtest.html.enというファイルをサーバに置きます。


で、件のアップローダですが、test.phpはアップロードできませんが、test.php.jaならアップロードできるわけです。

tok2proのApacheがコンテントネゴシエーションが有効であれば、test.php.jaはPHPとして実行されてしまいます。


PHPファイルを置ければあとはどうにでもなるので、PHPを使ってhtaccessなどを置いたのだと思われます。

犯人がログを改ざんするなどという気の利いたことをしていなければ、PHPファイルをアップロードした記録が残っているかもしれません。

id:neuromancer_sho

拡張子が最後に来ると決め付けちゃいけないんですね。

なるほど

2009/04/04 20:40:16
id:MinazukiBakera No.5

回答回数7ベストアンサー獲得回数1

ポイント24pt

これが直接の原否なのかどうかは分かりませんが、件のスクリプトでは拡張子のチェック部分に欠陥があり、チェックをすり抜けることが可能であるように思います。

たとえば以下のようなスクリプトは、一見すると .htaccess で終わるファイルを作らせないように見えます。

my $filename = ".htaccess";

if($filename =~/\.htaccess$/){

die "filename error";

}

open(OUT, "> $filename");

close(OUT);

しかし、

my $filename = ".htaccess\x0.txt";

として実行してみると、チェックを通り抜けて .htaccess というファイルが作成されるはずです。このように、ファイル名の途中に \x0 (NUL) を混入することでチェックをすり抜けることが可能となる場合があります。

なお、過去にはこのような問題が情報処理技術者試験でも出題されたことがあります。

参考: http://bakera.jp/ebi/topic/2519

ファイル名をチェックする際には、ファイル名全体が /^[-A-Za-z0-9]+$/ にマッチするかどうか確認するなどした方が良いと思います。

id:neuromancer_sho

ありがとうございます。

2009/04/04 20:44:20
  • id:pahoo
    回答を記入した後に気づいたのですが、ご質問のような場合は、アップロード可能な拡張子のみを通すロジックにした方が良いです。
    それでもアタックされるようでしたら、"./up" の書き込み権限が間違っているのではないでしょうか。
  • id:pigment
    拡張子については、#不正拡張子チェックとかでやってる気がする。
  • id:standard_one
    単にtelnetとかFTPで入られただけって可能性も・・・
  • id:shintabo
    あー、書いた後にもー1点だけ言わせてください。
    たぶん、Perl5.8だと思いますが、JcodeはEncodeのラッパーなので、
    使用するときは、
    是非
    use Encode

    (使用してないようなので、全く意味ないですが・・・)
  • id:neuromancer_sho
    pigmentさん
     pahooさん 2009-04-01 07:30:15の言っていることはそういう意味じゃないですよ。偉そうな書き方の割には分かってないですね。
  • id:pigment
    「不正拡張子のチェック」ではなく、「通して良い拡張子のチェック」をするべきだという意見ですよね?そうしたほうがチェックするファイル拡張子の種類を抑えることが出来ます。
    しかし、自分が見た限りでは、「不正拡張子チェック」に問題はないと思います。
    (きちんと「.htaccess」はハジカレルと思います。)
    つまり、そこを修正しても、結果は同じなのではないでしょうか?
    ちなみに不正なディレクトリが作成されてしまうのは気がつきましたが、こちらも、「.htaccess」がアップされることとは関係なさそうなので黙ってました。
    現時点では「CGI経由じゃない」という意見からは変わっていません。
    standard_oneさんの意見が正しいかもしれません。
    FTPでもパスワードが簡単であればすぐにクラックされます。
    事実そのようなクラックを受け、哀れな姿になってしまったレンサバ業者もいます。
    tok2proを使ったことがないのでわかりませんが、レンタルサーバであれば、どこかにftp.logとかweb.logとかないでしょうか?もしあれば何かわかるかもしれませんね
    ただしFTPで入ることができる場合には証拠隠滅も容易ですので、
    パスワードを変更してみることをお勧めします。
  • id:pahoo
    言葉足らずだったようで申し訳ありません。
    「通して良い拡張子のチェック」の件は、上で pigment さんがコメントしている通りです。

    tok2proの仕様は分かりませんが、".htaccess "(最後に空白文字あり)が入ってきた場合、不正拡張子チェックをパスしますが、セーブされるときに ".htaccess"(最後の空白は除かれる)になっていないだろうかという懸念があります。ですので、#1の回答で終端文字 $ を省いてみてくださいと述べました。実際に試してみてください。

    それから気になったのが、ファイル保存後のパーミッション変更 chmod (0666, "$upload_path") です。
    スクリプト上は問題ないと思うのですが、もし別ルートで侵入されているとすると、"hoge.txt" でアップしたものを ".htaccess" にリネームすることができてしまいます。
    不正ファイルがスクリプトの LOG に残っていないとすると、別ルートで侵入されている可能性が高いですね。

    あとは、tok2proの仕様そのものの問題でしょうか。
    ググってみると、パーミッション変更がうまくできないというような発言も見られますので、念のためフォルダやファイルのパーミッションがスクリプトで設定された通りになっているかどうか確認してください。
  • id:pigment
    おぉ、最後に空白てのは気がつきませんでした。
  • id:core_dump
    CGIのパラメータのfilenameに"a.shtml\x00hoge.jpg"のようなデータがきた場合には現状の拡張子チェックは機能していない気もします。
    tok2proではSSIが使えるようですが(どの機能が使えるかはググっても見つかりませんでしたが)、SSIのexec cmdが使えるなら上記と組み合わせて勝手な事ができるかもしれませんね。

    また同様にfilenameに"/.."等で終わる値を入れた場合、CGI.pm由来のtmpFileName()のファイル名でupの上にファイルを置ける気もします。
    #perl自体ひさしぶりに見るので、曖昧な書き方ですいません。

    あと、index.htmlが置き換えられてるならlog.txtもあてにならないですね。
  • id:neuromancer_sho
    みなさんありがとうございました。
    cgiを消すと攻撃が止むのでFTPパスワードがばれてたのではない様です。

    教えてもらった部分を参考に修正したら、攻撃が止んだみたいです。
    これが原因だったというのをまだはっきり絞り込んではいません。


この質問への反応(ブックマークコメント)

トラックバック

  • perl - tnek-cgi@CodeRepos - nms-cgi 再び 404 Blog Not Found 2009-04-03 10:45:47
    これを見ていたたまれなくなったので。 perlでアップローダを作ったのですが、クラックを受けている様なんです。 ./up の配下にしかアップロード出来ない様にしたつもりが、その上
「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません