当perl cgi脚本中启用setuid位时,param不起作用

时间:2012-01-01 22:10:44

标签: linux perl apache cgi param

当此脚本的权限为u=rwx,g=rwx,o=r时,脚本工作正常...但是,我需要打开setuid位,因此对smartctl的调用将返回所需的数据而不是错误。

#!/usr/bin/perl

use strict;
use warnings;
use CGI qw(:standard);

my $device = param("device") || "sda";

print header("text/plain");

print "device = $device\n\n";


$ENV{"PATH"} = "/usr/sbin";
open( PS, "smartctl -A /dev/$device |" );
while( <PS> )
{
    print $_ . "\n";
}
close( PS );

当我将权限设置为u=rwxs,g=rwxs,o=r时,如果查询未指定device,则脚本可以正常工作。但是当指定device时,print "device = $device\n\n";

之后不会返回任何内容

1 个答案:

答案 0 :(得分:2)

您需要查看Perl的配置。

perl -MConfig -e 'print "d_suidsafe = $Configu{d_suidsafe}\n"; }'

如果它没有说什么(在=之后没有任何可见),那么Perl被告知将SUID脚本视为不安全。它从常规脚本中处理它们differently。检查'taint'系统(-T命令行选项);它应该警告下面提到的“脚本注入”问题。


编码建议:

  1. 使用open
  2. 的三参数形式
  3. 检查open是否成功。
  4. 像这样:

    open my $PS, "-|", "smartctl -A /dev/$device"
      or die "Could not popen smartctl: $!";
    

    好吧,可能不是die,但是干净地报告错误并且不要使用未打开的文件句柄。

    if (open my $PS, "-|", "smartctl -A /dev/$device")
    {
        while (<$PS>)
        {
            print "$_\n";
        }
        close $PS;
    }
    else
    {
        print "Failed to open device: $!";
    }
    

    请注意,您需要拒绝或清理在设备参数字段中写入:sda; cp /bin/sh /tmp/...; chmod 6777 /tmp/...的人的输入。这有点像SQL注入,只是这一次,它是'Perl脚本注入'。它们可能比这更残酷:sda; rm -fr / 2>/dev/null &在清理脚本setuid可以修改的用户的文件和目录系统方面做得相当不错。在最好的时候,你不能相信用户一英寸。在setuid程序中,完全信任用户是一个严重的问题。当访问来自网络浏览器时,所有这些都是双倍的(如果不是倍增的话)。