使用Perl CGI程序以root权限运行脚本

3
我有一个Perl CGI程序,应该允许用户从文件系统中选择一些文件,然后通过Rsync发送到远程服务器。所有的HTML都是由Perl脚本生成的,并且我使用查询字符串和临时文件来营造类似于有状态交易的假象。Rsync部分是一个单独的shell脚本,使用文件名作为参数调用(该脚本还发送电子邮件和一堆其他东西,这就是为什么我没有将其移动到Perl脚本中的原因)。我想使用不需要密码的sudo,然后我设置了sudoers以允许apache用户无需密码运行脚本并禁用requiretty,但我仍然在日志中收到关于没有tty的错误。然后我尝试使用su -c scriptname,但也失败了。
总之,使用Perl CGI脚本通过sudo调用Bash脚本是否不好的实践?你如何处理Perl CGI脚本的特权升级?Perl 5.10 on Linux 2.6 Kernel。
相关代码:(LFILE是包含文件系统中所有文件数组索引的文件)
elsif ( $ENV{QUERY_STRING} =~ 'yes' ) {
      my @CMDLINE = qw(/bin/su -c /bin/scriptname.sh);
      print $q->start_html;
      open('TFILE', '<', "/tmp/LFILE");
      print'<ul>';
      foreach(<TFILE>) {
         $FILES[$_] =~ s/\/.*\///g;
         print "Running command @CMDLINE $FILES[$_]";
         print $q->h1("Sending File: $FILES[$_]") ; `@CMDLINE $FILES[$_]` or print $q->h1("Problem: $?);

1
“使用Perl CGI脚本通过sudo调用Bash脚本是一种糟糕的做法吗?” 是的,这是不好的做法。相反,应该为非root用户设置SSH密钥。 - ThisSuitIsBlackNot
我的问题的答案是 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no。 - GL2014
1
这不是一个很好的解决方案,因为它让你容易遭受中间人攻击,因为你不再检查你连接到的主机是否是你认为的那个主机。通过sudo授予您的web服务器用户超级用户特权也是一个非常糟糕的想法(TM)。 - ThisSuitIsBlackNot
当CGI通过反引号或system()调用scp/rsync等命令时,由于没有tty,我无法使它们正常工作。这个问题的正确解决方案是什么? - GL2014
一个选择是使用队列系统。你的CGI程序所做的就是将作业添加到队列中;另一个(非CGI)以特权用户身份运行的程序将作业从队列中取出并运行。这样可以解决很多安全问题。请注意,大多数队列系统都可以通过网络工作,因此执行作业的程序可以在远程系统上运行。有关其他建议,请参见类似的问题 - ThisSuitIsBlackNot
显示剩余2条评论
1个回答

1
然而,无论你最终如何操作,都必须小心谨慎。你希望尽量减少权限提升攻击的机会。记住这一点... sudo并不是用户(或进程)以增加的特权执行代码的唯一方式。对于这种类型的应用程序,我会利用设置了setuid位的程序。
  1. 编写一个程序,可以由适当权限的用户(在这种情况下为root,但请参见下面的警告)运行,以执行需要该特权的操作。 (这可能是您已经拥有并在问题中引用的脚本。)使此程序尽可能简单,并花费一些时间确保其编写良好且适当安全。

  2. 通过执行以下操作将“setuid位”设置在程序上:

    chmod a+x,u+s transfer_file
    

    这意味着任何人都可以执行该程序,但它以程序所有者的权限而不仅仅是程序用户的权限运行。

  3. 从现有的(非特权的)CGI脚本调用(特权的)传输程序。

现在,为了尽可能地保持所需权限的低限,我强烈建议避免以root身份执行传输操作。相反,创建一个拥有必要权限但没有更多权限的单独用户,并将该用户设置为setuid程序的所有者。这样,即使程序容易被利用,攻击者也只能使用该用户的权限,而不是root的权限。
在设置类似于此的内容时,有一些重要的“陷阱”。如果遇到问题,请再次在本网站上询问。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接