setuidされたPerlについての調査を行った。
kernelレベルではまたどうもややこしくなるようである。ここでは、単純にTaintモードの確認を行う。
#!/usr/bin/perl -T
use strict;
use warnings;
#my $fn = sprintf("/tmp/%ld.tmp", time);
my $fn = shift || die "usage: $0 touch_file_name\n";
print $fn, "\n";
open FH, ">$fn" || die "open failure. $!\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;
$ chmod u+s setuserid.pl $ chmod g+s setuserid.pl $ ls -l setuserid.pl -rwsr-sr-x ... setuserid.pl* $ su xxxxx(別のユーザ) $ ./setuserid.pl /tmp/hoge Insecure dependency in open while running setuid at /.../setuserid.pl line xx.
perlsecにあるとおり、引数から渡されてきたものをそのままファイル名としてopen私用とすると、汚染されていると見なされ、上記のようなエラーになる。これを回避するには、正規表現をバイパスさせる手法がperlsecに挙げられている。
ここでは、ファイル名をtimeの秒数で生成するようにしてみる。
#my $fn = sprintf("/tmp/%ld.tmp", time);
my $fn = shift || die "usage: $0 touch_file_name\n";
→
my $fn = sprintf("/tmp/%ld.tmp", time);
#my $fn = shift || die "usage: $0 touch_file_name\n";
実行結果 $ su xxxxx(別のユーザ) $ ./setuserid.pl /tmp/1175567398.tmp $ more /tmp/1175567398.tmp REAL_USER_ID(UID) = 600 EFFECTIVE_USER_ID(EUID) = 500 REAL_GROUP_ID(GID) = 600 600 EFFECTIVE_GROUP_ID(EGID) = 500 600
とりあえず今回はここまで。setuid、難しい・・・。