- PR -

webアプリケーションの脆弱性

投稿者投稿内容
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-12-15 13:56
ども、ほむらです。
僕もCGIを書いている身として煮詰めてみたいので。。
--------------
がるがる氏へ
以下必要部分の順序を整理ながら
中略させていただいてますm(__)m
引用:

まず「Bad Request」ですが。
これをApacheが出している場合、恐らくはパラメタが純粋に足りなかった
のだとおもうので、この辺はHTTP要求のあたりを調べてみてください。
昔はよかったのですが、最近は結構色々なヘッダが必須になっている
みたいなので。

--- 中略です ---

もう一つ。
よく、スクリプト系(に限らないのですが)で、データを読むときに
read(標準入力, 入力サイズ)
という書式があると思うのですが。
ここの入力サイズが1024で、一方の標準入力に10バイトしかデータ
がない場合。
いみじくも「タイムアウトするまで待たされる」とかかれてますが。
この「1024バイトと偽って10バイトのデータを送る」方法で、例えば
数千件のアクセスをいきなり要求されたら。
送る側は、せいぜい10*数千で、小さくはない、程度の画像を一枚送る
程度のトラフィックの負担になります。
サーバ&Webサービスはどうなるでしょう?


この動作はただしいと思います。
WebサーバーはContent-Lengthで指定されたサイズの入力があるまで
リモートホストからの通信を待ちますのでデータのサイズが足りなければ
タイムアウトになります。
また、タイムアウトになるときに送るといっていて実際のデータがきていないのですから
Bad Requestも正常のように思います。
仕様からくる現象ですのでCGIでは対処出来ないでしょう。

ちなみに、SCOがされていましたね(笑。
このDoS攻撃に対する専用のセキュリティソフトはあるみたいですが。。

引用:

次に。
ちと、CONTENT_LENGTH周りの挙動を細かく追っていきたいと思います。
MethodがPOSTの場合、多くのプログラムでは「CONTENT_LENGTHの長さ分
だけのデータが入ってくる」事を前提にプログラムが作成されています。

さて。
よくあるパターンですが「ダウンロードするデータのサイズを限定したい」
という要求があったとします。画像掲示板系なんかで顕著ですね。
この場合の制限は「どこのデータを見て」チェックしているのでしょう?
もし「CONTENT_LENGTH」をベースにしている場合。「実データは大きく
CONTENT_LENGTHパラメタの値は小さく」したらどうなりますか?
もし実データのサイズをベースにしている場合。そこで想定を超える
巨大なデータがダウンロードされたときにプログラムはきちんと
耐えられるでしょうか?


僕の書き方が特殊なのでしょうか?
Perlでは、sysread(STDIN, $httpRequest, $ENV{'CONTENT_LENGTH'});
として記述しています。
この場合を考えたとき、Content-Lengthの値の大小にかかわらず
標準入力以上にはなりませんし、またContent-Lengthを超えることもありません。
危険だとすれば両方を大きくした場合ですがこれもCGIでは
微妙ではないでしょうか?
まぁ、読み込む前に調節すればいいのかな〜

#個人的に思うにサイタイジング(?)でURLエスケープを忘れている人は時々いますね。
#日本語に対応していればそんなことはおこらないはずですけど
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-12-15 14:22
ども、ほむらです。
長くなってしまったので分けされていただきました。
-------
おばけ氏へ
引用:

やはり、CookieやFormの値というのは悪意のあるユーザの攻撃に使われると考え
なければならない、というスタンスが大切ですね。


ですね。同感です。
その関係でしょうか最近では、hiddenは使わずに
Session変数を使用する場面がおおいみたいですね。
まぁ、だからといって安全になったということでもないかもしれませんが。
改ざんについてはだいぶ安心できる環境になってますよね。
#そのうち、hidden=セキュリティホールみたいな考え方の人がでてきそう(笑

ですが、僕の場合クッキーはほとんど使用したことはない(リロード対策くらい?)のですが
hiddenはわりと使用します。(CGIなのでSessionが使えないんですよ(笑 )

僕がhiddenで使用する対象になるのはCGIの内部で静的に定義されているデータ等や
読み取られても問題のないものです。

#最近タイムスタンプの使い方がわかったのでファイルを使用して
#セッション変数もどきを作ろうかと計画中
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2003-12-15 14:36
ども。がるです。
んと、同じく煮詰めたいネタなのでちと腰をすえて(笑

まず
・タイムアウトでDoSになる件
ですが。個人的には非常に微妙な扱いをしています。
というか、まず第一に
「どういう挙動の結果そうなるのか」
を認識していないケースが多くて。厳しい発言をするなら、
基礎動作をきちんと認識していない時点で「論外」と。

つぎに。
タイムアウト待ちは「わかっててやっていて」なお、非常に
微妙です。
仕様を突き詰めた結果として「リスク込みでそれでよい」となれば
それでよいのだと思うのですが。
実際にはその辺のリスクを考慮せずに「何でこうなるんだろう?」
となるケースが多く。
この場合に、非常に危険であると思ってます。
というか、この攻撃、比較的軽いリソースで行えてしまうので、
考慮からはずすにはちと…って部分があるので、いつも悩みます。
個人的には実はCONTENT_LENGTHは無考慮にすることが多いです。
まぁそれはそれで色々リスクがあるので、その辺はいつも考察が
欠かせない部分なのですが。

ちなみに
> 仕様からくる現象ですのでCGIでは対処出来ないでしょう。
そうでもないです。かなり環境は限定されますが。
知っている限り、C(およびC++)だと、非同期のread、というものが
あるので、少なくとも「タイムアウトの時間を任意に制御」したり
「タイムアウトであることを明確に把握」したりすることが出来ます。
ただ…知っている限りでは、Perlでは無理ですねぇ。システムコール
を直接呼べば可能なのですが(笑

> ちなみに、SCOがされていましたね(笑。
です。
あの辺が「リスクを飲んでの結果」かどうかはかなり微妙ですが:-P

> Perlでは、sysread(STDIN, $httpRequest, $ENV{'CONTENT_LENGTH'});
実データがCONTENT_LENGTH以上、の場合で危ないのは、実はCでCGI
を書いているときが一番顕著です。
スクリプト系やC++でstringを使っているときは、言語のバックボーンが
動的なメモリ確保をやっているので比較的楽かなぁ、と。

双方とも大きくした場合は…C++は回避が簡単に出来るのですが
(stringからの例外の捕捉)、Perlがもう一つ。
まったく対応できないわけではないのですが、比較的に面倒な
うえにきちんと処理をしているケースがほとんどないですね。

この辺を色々考えるに、個人的には「業務のCGIをPerlで組む」
のに、一定レベルの抵抗感がぬぐえないです。
環境が許せばC++、ないし「徹底的に突き詰めるのなら」Cで
記述しています。…もっとも、最近はほとんどC++で楽をしており
ますが(stringと、それ以上にclass、STLが手放せない)。

こーゆー部分って実はCGIの話ではずいぶんおざなりにされやすい
部分なんですが。
この辺をきちんと突き詰めておくと結構深くて面白いと思ってます。

# 次点は「セッションID」なのですが。
# そのうち突き詰めた話をぶちまけてみようかな?(笑


[ メッセージ編集済み 編集者: がるがる 編集日時 2003-12-15 14:49 ]
bun
会議室デビュー日: 2002/03/07
投稿数: 6
投稿日時: 2003-12-15 15:59
[quote]
がるがるさんの書き込み (2003-12-15 12:54) より:

引用:

MethodがPOSTの場合、多くのプログラムでは「CONTENT_LENGTHの長さ分
だけのデータが入ってくる」事を前提にプログラムが作成されています。
(中略)
そこで想定を超える巨大なデータがダウンロードされたときにプログラムはきちんと
耐えられるでしょうか?


あぁなるほど。いわゆるバッファオーバーフローの話ですね。
手元では Perl の CGI で試していたので、忘れていました。

引用:

こーゆー部分って実はCGIの話ではずいぶんおざなりにされやすい
部分なんですが。
この辺をきちんと突き詰めておくと結構深くて面白いと思ってます。


これらはどんなプログラミングでも必要なことなのに、
なんで Web アプリケーションの場合はおざなりにされちゃうんでしょうかね。

[ メッセージ編集済み 編集者: bun 編集日時 2003-12-15 16:00 ]
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2003-12-15 16:10
ども。がるです。
引用:

bunさんの書き込み (2003-12-15 15:59) より:
あぁなるほど。いわゆるバッファオーバーフローの話ですね。
手元では Perl の CGI で試していたので、忘れていました。


厳密にはバッファオーバフロー「だけ」ではないですね。
単純に、あまり巨大な変数は取れない場合があるので(原因は色々)。
バッファがあふれないにしても、変数として「取得できない」、
さらには「落ちる」というケースがたまにあるので。
ちなみに、この辺のテストをすると「Linuxってもろいなぁ」とか
思います :-P
そういう点で丈夫なのは例えばSolaris。Linuxは、2.4から大分
丈夫になってきたように思いますが…まだ微妙不安。

引用:

これらはどんなプログラミングでも必要なことなのに、
なんで Web アプリケーションの場合はおざなりにされちゃうんでしょうかね。


実はWebアプリケーション(ってかCGI)以外でも結構軽視されてます。
最近の風潮、って感じでしょうか?
最近のプログラマ/SEの方は、総じて基礎がしっかりしていないことが
多くて、上っ面だけ見て「こんなもんかなぁ」で終わってしまう
ケースが多いように思います。

実際にはある程度便利な機能というのは使わないと(生産性があがらない
ので)重要なのですが。
技術者たるもの、そのバックボーンに一度は思いをはせ、実装方法を
しり、っていう作業が必要だと思うんですけどね。

あと、多いのが「単一主義者」。あらゆるものを「単一のOS」「単一の
言語」「単一のDB」「単一の**」で片付けようとする。
複数のものを学んで、そこからベストチョイスを探すのって技術者の
仕事の一つだと、それは今でも思っているのですが。
そこまできちんと勉強する人は少ないですねぇ。

ちょいと厳しめの意見を書いてみました ^^;
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-12-15 17:40
ども、ほむらです。
---------
hose氏へ
スレとかけ離れていきそうなのでちょっと本題に
Webアプリケーションの脆弱性として代表的な物は
・リクエストデータの未チェック(未修正)によるプログラムの実行など
・hiddenデータの加工
・お気に入りや戻るなど想定外の経路
・クッキーデータの盗聴・改ざん?
とこんなところでしょうか?

加工や想定外の入力に関しては注意がいっているようですが
修正するロジックの中でただしいデータが別の形
(URLエンコードや本来入力されない書式)
できた場合にスルーしてしまうこともあるみたいですね

#IEの事を気にされているようですが、世間で言われているとおり
#IEのセキュリティホールは似たようなものばかりです。
#(それも拡大解釈に起因するところが大きいようですね)

-----
がるがる氏へ
>タイムアウトでDoSになる件
これはあとでてくる、想定以上のばかでかいメモリ確保と同等ですよね。
タイムアウトする間にリクエストがどんどんきて、新しいプロセスが立ち上がって
結果として、リソース不足になってサーバーダウン。。。
でも、こうやって考えるとタイムアウトはしなくてもいいんですよね。
原因はシステムリソースの減少ですから。

引用:

知っている限り、C(およびC++)だと、非同期のread、というものが
あるので、少なくとも「タイムアウトの時間を任意に制御」したり
「タイムアウトであることを明確に把握」したりすることが出来ます。


非同期処理ですか。
それならば確かにタイムアウトの検知はCGIできますね。
ただ、その場合だとCGIのタイムアウト時間は
サーバーのものよりも短くする必要がでてきますので、どうせならば
タイムアウトを監視するのでなく、
読み込みのサイズを監視したほうがいいのではないかなと思います

引用:

> Perlでは、sysread(STDIN, $httpRequest, $ENV{'CONTENT_LENGTH'});
実データがCONTENT_LENGTH以上、の場合で危ないのは、実はCでCGI
を書いているときが一番顕著です。


PerlもCも同じだと思うのですが・・・・
僕のプログラムの方法を中心に考えればContent-Lengthを使用するのならば
変数に保存してその変数を起点に処理していきますよね?
たとえば
query = (unsigned char *)malloc( contentLength );
fgets(stdin, query, contentLength);とか(?)

引用:

この辺を色々考えるに、個人的には「業務のCGIをPerlで組む」
のに、一定レベルの抵抗感がぬぐえないです。
環境が許せばC++、ないし「徹底的に突き詰めるのなら」Cで
記述しています。…もっとも、最近はほとんどC++で楽をしており
ますが(stringと、それ以上にclass、STLが手放せない)。


どうでしょう?やっぱり業務であってもCGIは多く使用されているのでしょうか?
個人的には業務ならばサーブレットや.NETの世界だと思うのですけど。。。

#STLは便利ですよね。
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2003-12-15 18:47
ども。がるです。

引用:

>タイムアウトでDoSになる件
これはあとでてくる、想定以上のばかでかいメモリ確保と同等ですよね。


です。この辺のリソース周りは、いつまでたっても面倒な話題
ですね(苦笑
でも、案外簡単に限界に引っかかる瞬間があるのが怖いです。

引用:

非同期処理ですか。
それならば確かにタイムアウトの検知はCGIできますね。
ただ、その場合だとCGIのタイムアウト時間は
サーバーのものよりも短くする必要がでてきますので、どうせならば
タイムアウトを監視するのでなく、
読み込みのサイズを監視したほうがいいのではないかなと思います


これは、私の場合は「どっちも」ですね。
マイクロスリープ(select)とかで一瞬ウェイトをおいて、読み込みが
進んでいなければきる、くらいの思い切った処理が、時々必要に
なってます。
ただ、非同期はなれないと面倒なので、教育には苦労します(苦笑

引用:

僕のプログラムの方法を中心に考えればContent-Lengthを使用するのならば
変数に保存してその変数を起点に処理していきますよね?
たとえば
query = (unsigned char *)malloc( contentLength );
fgets(stdin, query, contentLength);とか(?)


基本はこのパターンです。
で、やはりこれで「CONTENT_LENGTHを信用してしまう」ミスをやった
時に、ある人から「-1が入ってきたら?」
と一言で片付けられて、目からうろこが落ちたことがあります。
# mallocで-1って挙動保証ないんですよね ^^;

結局このあたりは「どこを切り捨てるか」っていうかなりシビアな
議論になるので、一概に正解がないあたりが難しいですね。
私も「データを基準にする」時と「CONTENT_LENGTHを基準にする」
時と、ケースbyケースで設計していますね。

引用:

どうでしょう?やっぱり業務であってもCGIは多く使用されているのでしょうか?
個人的には業務ならばサーブレットや.NETの世界だと思うのですけど。。。


私はCGIで作成することが多いですね。
単純に「細かいところまで手が届く」ので。特にC++の場合。

サーブレットはすきなのですがJSPが嫌いだったり(人にも寄るのですが、
デザインとロジックが分離していないところが苦手:同様にPHPもだめ)。
.NETは色々あってまだ手を出していないですね(いやまぁ単純にWindows
プラットフォームでの仕事をめったにしないだけなのですが。現状で、
Linuxで.NETを積極的に選択する理由も特に思い当たらないので)。

よく「大掛かりなものにはCGIは…」と倦厭する人が多いのですが、私の
場合、CGIで大掛かりなものを簡単に作る技術に慣れてしまったので、
あまり苦労はしてないです(笑

まぁ、この辺は「色々ためして」みつつ「どのような論点から」なにが
ベストなのかを見極めていけるのがベストなんだろうなぁ、って思います。

なんか話しが微妙にずれてきたので、この辺で(笑

スキルアップ/キャリアアップ(JOB@IT)