2011-04-28 141 views
1

我想在一个CGI程序(用Perl编写)中运行shell命令。我的程序没有root权限。它像没人一样运行。我想利用这个代码:如何以nobody用户身份在CGI程序中运行shell命令?

use strict; 
system <<'EEE'; 
awk '{a[$1]+=$2;b[$1]+=$3}END{for(i in a)print i, a[i], b[i]|"sort -nk 3"}' s.txt 
EEE 

我可以在命令行perl的成功运行我的代码,但不能作为CGI程序。

+1

'使用警告;'比'use strict'更重要;' – ysth 2011-04-28 04:48:05

回答

0

我确定nobody被允许运行shell命令。问题是nobody没有权限打开文件s.txt。将所有人的读取权限添加到s.txt,并将执行权限添加到每个目录中的所有人,最高达s.txt

+1

或awk不在过程的PATH变量中列出的路径之一,但我们真的不知道,因为没有错误检查。 – converter42 2011-04-28 05:32:09

0

我建议找出awk的全限定路径并直接指定它。可能没有人推出httpd在它的$ ENV {PATH}中有一个非常小的路径。显示$ ENV {PATH}我猜测会显示这个。

这是一件好事,我不会修改路径,而只是指定路径/​​ usr/bin/awk或不是。

如果您有shell访问权限并且可以使用,请输入'which awk'来找出它。

0

我可以在 perl文件中成功运行我的代码,但不能在cgi文件中运行。

你在什么网络服务器上运行?例如,Apache需要打印CGI头即print "Content-type: text/plain; charset=utf-8\n\n",或

use CGI; 
my $q = CGI->new(); 
print $q->header('text/html'); 

(见CGI

Apache会关于“脚本头过早结束”如果我说是日志(error.log)在conplain案子。

0

你可以做它内联,而无需掏钱到另一个进程......

if (open my $fh, '<', 's.txt') { 
    my %data; 
    while (<$fh>) { 
     my ($c1,$c2,$c3) = split; 
     $data{a}{$c1} += $c2; 
     $data{b}{$c1} += $c3; 
    } 
    foreach (sort { $data{b}{$a} <=> $data{b}{$b} } keys %{ $data{b} }) { 
     print "$_ $data{a}{$_} $data{b}{$_}\n"; 
    } 

} else { 
    warn "Unable to open s.txt: $!\n"; 
} 
1

基于对你的问题的代码,也有失败的,至少四种可能性。

  1. 没有人用户没有权限执行您的程序。
  2. 您的问题中的Perl代码没有shebang(#!)行。你试图运行awk,所以我假设你运行在某种形式的Unix上。如果你的代码缺少这一行,那么你的操作系统不知道如何运行你的程序。
  3. 文件s.txt不在执行程序的工作目录中,或者它不能被nobody用户读取。
  4. 无论出于何种原因,awk无法通过执行程序环境的PATH访问。

要快速诊断这些低级别问题,请尝试让所有错误输出显示在浏览器中。一种方法是在代码中的shebang行之后添加以下内容。

BEGIN { 
    print "Content-type: text/plain\n\n"; 
    open STDERR, ">&", \*STDOUT or print "$0: dup: $!"; 
} 

输出将呈现为纯文本而非HTML,但这是查看程序输出的临时度量。通过将其包装在BEGIN块中,代码在解析后立即执行。重定向STDERR意味着您的浏览器也可以获得任何写入标准输出的内容。

另一种方法是使用CGI::Carp模块。

use CGI::Carp 'fatalsToBrowser'; 

这样,错误会发送到浏览器,也发送到Web服务器的错误日志。

如果您仍然发现服务器发生500系列错误,则问题发生在较低级别:可能是某些启动失败perl。去检查你的服务器的错误日志。一旦你的程序正在执行,你可以删除这个临时的错误输出重定向。

最后,我建议改变你的程序

#! /usr/bin/perl -T 

BEGIN { print "Content-type: text/plain\n\n"; } 

use strict; 
use warnings; 

$ENV{PATH} = "/bin:/usr/bin"; 

my $input = "/path/to/your/s.txt"; 

my $buckets = <<'EOProgram' 
{ a[$1] += $2; b[$1] += $3 } 

END { for (i in a) print i, a[i], b[i] } 
EOProgram 

open STDIN, "-|", "awk", $buckets, $input or die "$0: open: $!"; 
exec "sort", "-nk", 3      or die "$0: exec: $!"; 

-T开关使安全数据流分析称为taint mode阻止你使用unsanitized输入对系统的操作,如openexec,等等,一个攻击者(或提供意外输入的良性用户)可能会用来损害您的系统。您应该始终将-T添加到CGI程序以及代表另一个用户运行的任何其他代码。

鉴于awk程序的性质,文本/纯文本的内容类型似乎是合理的。尽快输出。

启用污染模式后,请明确说明PATH环境变量的值。如果您坚持使用您的程序继承的任何不可信的PATH,尝试运行外部程序将失败。

确定输入的完整路径。这将消除惊喜。

使用openexec的多参数形式消除了shell及其参数解析。 (为了完整性,system也有一个类似的多参数形式。)是的,这样写就可以意味着being a little more deliberate(比如打破争论并自己设置管道),但它也避免了令人讨厌的惊喜。

相关问题