なお、このtaintperlやPerlの-Tオプションを指定した場合、この手のブラックリスト方式のメタキャラクタ漏れによる脆弱性は発生しない(記号を削るという方式では汚染は除去されていないとみなされる)。
$a = $ARGV[1]; $a =~ s/\W//g; # 汚染されている $a =~ s/^([a-z]+)$//; $a = $1; # 汚染されていない
というわけで、Perlでは、CGIというものが普及する以前から、
そのため、記号を全部削るという対策が普及しました。のような対策は「言語として」推奨されていない(それでもそういう対策をしちゃう人は別問題として)。
ホントかな? ホントかな?
試しに、以下のスクリプトを書いてみましたよ。
#!/usr/bin/perl -T use strict; my $file = $ARGV[0]; open FH, $file;
コマンドライン引数の値をそのまま引数 2個形式 open
の第2引数に渡しちゃっているという、明らかにダメなプログラム例。話をわかりやすくするため、サンプルも敢えてシンプルにいきますよ。
これ、例えば taint.pl
なんて名前で保存して実行権限付加しておいて、以下のように呼び出したりしても、Perl は例外を発生しません。
murachi@maha ~ $ ./taint.pl hoge.txt murachi@maha ~ $
で、以下のように、open
命令の第2引数に渡す文字列がモードを指定することになるような値を、コマンドライン引数に指定すると、例外を発生します。
murachi@maha ~ $ ./taint.pl '>hoge.txt' Insecure dependency in open while running with -T switch at ./taint.pl line 5. murachi@maha ~ $
それではおさかなラボの人が「これでは汚染が除去されたとは看做されないよ」とおっさられている方法でサニタイズした場合、どうなるでしょうか? (ここでは敢えて、悪意をこめてこの言葉を使用します。もちろん、このようなコーディングを推奨するわけではありません。) スクリプトを以下のように修正してみましょう。
#!/usr/bin/perl -T use strict; my $file = $ARGV[0]; $file =~ s/\W//g; # ←この行を追加 open FH, $file;
ここで、先ほどと同じコマンド呼び出しで試してみると、例外は発生することなく、スクリプトは実行されます。
murachi@maha ~ $ ./taint.pl '>hoge.txt' murachi@maha ~ $
それじゃあ置換操作が行われちゃっているとことごとく汚染フラグは下ろされちゃうのかっていうとそういうわけでもなくて、例えば以下のように、状況的に間違っちゃっているフィルタリングを行っているような場合、
#!/usr/bin/perl -T use strict; my $file = $ARGV[0]; $file =~ s/%([\da-f][\da-f])/pack 'H2', $1/eg; # ←この状況では無意味な置換 open FH, $file;
以下のように呼び出すことで、やはり例外は発生する。
murachi@maha ~ $ ./taint.pl '%3ehoge.txt' -bash: ./taint.pl: /usr/bin/perl: bad interpreter: Text file busy murachi@maha ~ $
何故なら間違った置換操作によって
が %3e
に置換されるから。そして、その状態で >
open
の第2引数に渡すと読み込みモード以外のモードになってしまうので、安全では無いとして例外が発生する、と。
つまり、Taint mode における Perl は、外部入力由来の値について、適切な置換操作による汚染の除去が行われたかどうかに関わらず、その値の使用時に安全性のチェックを行うと。そして、その値を利用する状況に応じて、その値が安全では無いと看做されるのであれば、例外を発生する、ということなわけだわね。
セコメントをする