Perl/codepiece/setuid02 ではコマンドライン引数の汚染除去を試みた。
今回は、ファイルから読み取った値の汚染除去を試みる。
perlsec( http://perldoc.perl.org/perlsec.html )にあるとおり、Taintモードが有効な場合、Perlプログラムの"外部"から取得される変数は基本的に汚染されていると見なされる。perlsecに上げられているものとして以下が汚染されたものと見なされる。
これらの値を使って以下の操作を行う場合、致命的なエラーが発生する。
但し、Perl5.8.8のperlsecによると、以下の場合はTaintチェックは行われない。
以下のコードピースで、ファイルから読み取った値の汚染除去を試みる。
#!/usr/bin/perl -T use strict; use warnings; my $fn = shift or die "usage: $0 conffile\n"; my $re_filename = qr|[0-9A-Za-z_,\-\./]+|; die "$fn is not untained." unless $fn =~ /^($re_filename)$/; $fn = $1; open FH, "<$fn" or die "open failure. $!\n"; # 引数で渡されたファイル(conffile)から、出力先のファイル名を取得する。 # # conffileは、出力先のファイル名が一行で記述されているテキストファイルとする。 # 例: # /tmp/hoge.txt<NL><EOF> # my $outfile = <FH>; close FH; # remove new line chomp $outfile; $fn = $outfile; # 汚染除去を行う。 die "$fn is not secure." unless $fn =~ /^($re_filename)$/; $fn = $1; open FH, ">$fn" || die "open failure. $!\n"; print FH "$outfile\n"; print FH "REAL_USER_ID(UID) = $<\n"; print FH "EFFECTIVE_USER_ID(EUID) = $>\n"; print FH "REAL_GROUP_ID(GID) = $(\n"; print FH "EFFECTIVE_GROUP_ID(EGID) = $)\n"; close FH;
例えば上記コードピースで、出力ファイル名をキメ打ちにした場合も、正常に終了する。
print FH "$outfile\n";
上記コードが有るにもかかわらず正常に終了するのは、printが汚染チェックを行わないからである。