buk*_*zor 5 bash perl suid taint suexec
我正在尝试向旧脚本添加一项功能。该脚本是 suid,并使用 perl -T(污点模式:man perlsec),以提高安全性。我需要添加的功能是用Python实现的。
问题是我无法说服 perlsec 保留 suid 权限,无论我如何清理环境和命令行。
这很令人沮丧,因为它保留了其他二进制文件(例如 /bin/id)的 suid。/usr/bin/perl 是否有未记录的特殊情况?这似乎不太可能。
有谁知道如何进行这项工作?(按原样:我们没有资源来重新构建整个事情。)
解决方案:(根据@gbacon)
# use the -p option to bash
system('/bin/bash', '-p', '-c', '/usr/bin/id -un');
# or set real user and group ids
$< = $>;
$( = $);
system('/usr/bin/python', '-c', 'import os; os.system("/usr/bin/id -un")');
Run Code Online (Sandbox Code Playgroud)
这给出了期望的结果!
这是我的脚本的精简版本,它仍然显示了我的问题。
#!/usr/bin/perl -T
## This is an SUID script: man perlsec
%ENV = ( "PATH" => "" );
##### PERLSEC HELPERS #####
sub tainted (@) {
# Prevent errors, stringifying
local(@_, $@, $^W) = @_;
#let eval catch the DIE signal
$SIG{__DIE__} = '';
my $retval = not eval { join("",@_), kill 0; 1 };
$SIG{__DIE__} = 'myexit';
return $retval
}
sub show_taint {
foreach (@_) {
my $arg = $_; #prevent "read-only variable" nonsense
chomp $arg;
if ( tainted($arg) ) {
print "TAINT:'$arg'";
} else {
print "ok:'$arg'";
}
print ", ";
}
print "\n";
}
### END PERLSEC HELPERS ###
# Are we SUID ? man perlsec
my $uid = `/usr/bin/id --user` ;
chomp $uid;
my $reluser = "dt-pdrel";
my $reluid = `/usr/bin/id --user $reluser 2> /dev/null`;
chomp $reluid;
if ( $uid ne $reluid ) {
# what ? we are not anymore SUID ? somebody must do a chmod u+s $current_script
print STDERR "chmod 4555 $myname\n";
exit(14);
}
# comment this line if you don't want to autoflush after every print
$| = 1;
# now, we're safe, single & SUID
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# BEGIN of main code itself
print "\nENVIRON UNDER BASH:\n";
run('/bin/bash', '-c', '/bin/env');
print "\nTAINT DEMO:\n";
print "\@ARGV: ";
show_taint(@ARGV);
print "\%ENV: ";
show_taint(values %ENV);
print "`cat`: ";
show_taint(`/bin/cat /etc/host.conf`);
print "\nworks:\n";
run('/usr/bin/id', '-un');
run('/usr/bin/id -un');
print "\ndoesn't work:\n";
run('/bin/bash', '-c', '/usr/bin/id -un');
run('/bin/bash', '-c', '/bin/date >> /home/dt-pdrel/date');
run('/bin/date >> /home/dt-pdrel/date');
run('/usr/bin/python', '-c', 'import os; os.system("/usr/bin/id -un")');
run('/usr/bin/python', '-c', 'import os; os.system("/usr/bin/id -un")');
sub run {
my @cmd = @_;
print "\tCMD: '@cmd'\n";
print "\tSEC: ";
show_taint(@cmd);
print "\tOUT: ";
system @cmd ;
print "\n";
}
Run Code Online (Sandbox Code Playgroud)
这是输出:
$ id -un
bukzor
$ ls -l /proj/test/test.pl
-rwsr-xr-x 1 testrel asic 1976 Jul 22 14:34 /proj/test/test.pl*
$ /proj/test/test.pl foo bar
ENVIRON UNDER BASH:
CMD: '/bin/bash -c /bin/env'
SEC: ok:'/bin/bash', ok:'-c', ok:'/bin/env',
OUT: PATH=
PWD=/proj/test2/bukzor/test_dir/
SHLVL=1
_=/bin/env
TAINT DEMO:
@ARGV: TAINT:'foo', TAINT:'bar',
%ENV: ok:'',
`cat`: TAINT:'order hosts,bind',
works:
CMD: '/usr/bin/id -un'
SEC: ok:'/usr/bin/id', ok:'-un',
OUT: testrel
CMD: '/usr/bin/id -un'
SEC: ok:'/usr/bin/id -un',
OUT: testrel
doesn't work:
CMD: '/bin/bash -c /usr/bin/id -un'
SEC: ok:'/bin/bash', ok:'-c', ok:'/usr/bin/id -un',
OUT: bukzor
CMD: '/bin/bash -c /bin/date >> /home/testrel/date'
SEC: ok:'/bin/bash', ok:'-c', ok:'/bin/date >> /home/testrel/date',
OUT: /bin/bash: /home/testrel/date: Permission denied
CMD: '/bin/date >> /home/testrel/date'
SEC: ok:'/bin/date >> /home/testrel/date',
OUT: sh: /home/testrel/date: Permission denied
CMD: '/usr/bin/python -c import os; os.system("/usr/bin/id -un")'
SEC: ok:'/usr/bin/python', ok:'-c', ok:'import os; os.system("/usr/bin/id -un")',
OUT: bukzor
CMD: '/usr/bin/python -c import os; os.system("/usr/bin/id -un")'
SEC: ok:'/usr/bin/python', ok:'-c', ok:'import os; os.system("/usr/bin/id -un")',
OUT: bukzor
Run Code Online (Sandbox Code Playgroud)
您需要将您的真实用户 ID 设置为有效(suid-ed)用户 ID。您可能想对您的真实组 ID 执行相同的操作:
\n#! /usr/bin/perl -T\n\nuse warnings;\nuse strict;\n\n$ENV{PATH} = "/bin:/usr/bin";\n\nsystem "id -un";\nsystem "/bin/bash", "-c", "id -un";\n\n# set real user and group ids\n$< = $>;\n$( = $);\n\nsystem "/bin/bash", "-c", "id -un";\nRun Code Online (Sandbox Code Playgroud)\n示例运行:
\n$ ls -l suid.pl\n-rwsr-sr-x 1无人 nogroup 177 2010-07-22 20:33 suid.pl\n\n$ ./suid.pl\nnobody\ngbacon\nnobody\n
您看到的是记录的bash行为:
\n\n\n
-p打开特权模式。在此模式下,不会处理
\n$BASH_ENV和文件,shell 函数不会从环境继承,并且、和变量(如果出现在环境中)将被忽略。如果 shell 启动时有效用户(组)id 不等于真实用户(组)id,并且未提供该选项,则执行这些操作并将有效用户 id 设置为真实用户 id。如果在启动时提供该选项,则不会重置有效用户 ID。关闭此选项会导致有效用户和组 ID 设置为真实用户和组 ID。$ENVSHELLOPTSBASHOPTSCDPATHGLOBIGNORE-p-p
这意味着您还可以
\n#! /usr/bin/perl -T\n\nuse warnings;\nuse strict;\n\n$ENV{PATH} = "/bin:/usr/bin";\n\nsystem "/bin/bash", "-p", "-c", "id -un";\nRun Code Online (Sandbox Code Playgroud)\n要得到
\n没有人\n
回想一下,传递多个参数可以system绕过 shell。单个参数确实会进入 shell,但可能不会bash\xe2\x80\x94 看一下 的输出perl -MConfig -le 'print $Config{sh}'。
也许考虑使用use English '-no_match_vars';精神理智:\n它将提供$GID、$EGID、$UID、$EUID等。