我想在一个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程序。
我想在一个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程序。
我确定nobody
被允许运行shell命令。问题是nobody
没有权限打开文件s.txt
。将所有人的读取权限添加到s.txt
,并将执行权限添加到每个目录中的所有人,最高达s.txt
。
或awk不在过程的PATH变量中列出的路径之一,但我们真的不知道,因为没有错误检查。 – converter42 2011-04-28 05:32:09
我建议找出awk的全限定路径并直接指定它。可能没有人推出httpd在它的$ ENV {PATH}中有一个非常小的路径。显示$ ENV {PATH}我猜测会显示这个。
这是一件好事,我不会修改路径,而只是指定路径/ usr/bin/awk或不是。
如果您有shell访问权限并且可以使用,请输入'which awk'来找出它。
我可以在 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案子。
你可以做它内联,而无需掏钱到另一个进程......
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";
}
基于对你的问题的代码,也有失败的,至少四种可能性。
#!
)行。你试图运行awk
,所以我假设你运行在某种形式的Unix上。如果你的代码缺少这一行,那么你的操作系统不知道如何运行你的程序。s.txt
不在执行程序的工作目录中,或者它不能被nobody用户读取。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输入对系统的操作,如open
,exec
,等等,一个攻击者(或提供意外输入的良性用户)可能会用来损害您的系统。您应该始终将-T
添加到CGI程序以及代表另一个用户运行的任何其他代码。
鉴于awk程序的性质,文本/纯文本的内容类型似乎是合理的。尽快输出。
启用污染模式后,请明确说明PATH环境变量的值。如果您坚持使用您的程序继承的任何不可信的PATH,尝试运行外部程序将失败。
确定输入的完整路径。这将消除惊喜。
使用open
和exec
的多参数形式消除了shell及其参数解析。 (为了完整性,system
也有一个类似的多参数形式。)是的,这样写就可以意味着being a little more deliberate(比如打破争论并自己设置管道),但它也避免了令人讨厌的惊喜。
'使用警告;'比'use strict'更重要;' – ysth 2011-04-28 04:48:05