Perl CGI脚本无法创建文件

Perl CGI脚本无法创建文件,perl,file,permissions,cgi,Perl,File,Permissions,Cgi,我有下面的CGI脚本,它启动一个模块,创建一个PNG文件,然后显示它 #!/usr/bin/perl use RRDs; use CGI; main: { my $cgi = new CGI; my $filename = $cgi->param('filename'); print "Content-type: text/html\n\n"; my $curr_time = time(); my $start_time = $curr_time-3600; RRDs::graph("

我有下面的CGI脚本,它启动一个模块,创建一个PNG文件,然后显示它

#!/usr/bin/perl

use RRDs;
use CGI;

main:
{
my $cgi = new CGI;
my $filename = $cgi->param('filename');
print "Content-type: text/html\n\n";
my $curr_time = time();
my $start_time = $curr_time-3600;
RRDs::graph("$filename", "--start", "$start_time", "DEF:DiskC=c.rrd:DiskC:AVERAGE", "AREA:DiskC#0000FF");
my $err = RRDs::error();
print "<HTML><HEAD><TITLE>Disk C Utilization</TITLE></HEAD><BODY><H1>Disk C Utilization</H1><BR>$err<img src=\"$filename\"/></BODY></HTML>";
}
#/usr/bin/perl
使用RRD;
使用CGI;
主要内容:
{
my$cgi=新cgi;
我的$filename=$cgi->param('filename');
打印“内容类型:text/html\n\n”;
我的$curr_time=time();
我的$start\u time=$curr\u time-3600;
RRDs::图形(“$filename”、“--start”、“$start_time”、“DEF:DiskC=c.rrd:DiskC:AVERAGE”、“AREA:DiskC#0000FF”);
我的$err=RRDs::error();
打印“磁盘C利用率磁盘C利用率
$err”; }
graph方法表示无法创建PNG文件。如果我在命令中运行这个脚本,它可以正常工作,所以我认为这是权限问题。我已经在cgi脚本文件夹中设置了chmod 755。你有什么建议?这与Apache2设置有关吗?

嗯,检查日志:)

$filename不是您要使用的文件名,它可以是浏览器发送的任何内容,甚至可以是

F:/bar/bar/bar/bar/bar/bar/UHOH.png

服务器上不太可能存在

F:/bar/bar/bar/bar/bar/bar/bar/UHOH.png

您想生成一个文件名,可能像

您还希望将文件放在提供图像服务的Web服务器目录中(而不是cgi bin)

您还需要使用

File::Type::WebImages
来使用magic确定web图像文件类型,并确保文件名具有适当的扩展名,以便服务器将发送适当的标题

别忘了

chmod
文件正确地

chmod777
解决了我的问题

除非有理由,否则不要将文档存储到文件中:它速度慢,并且会带来各种潜在危险

您似乎不会在不同的请求上重用相同的图像,这可能就是原因之一


相反,教你的CGI脚本直接输出图像,这取决于它的调用方式(或编写第二个这样做的脚本)。

这个脚本实际上是一个测试,当然,一旦我设置好了所有内容,目录和检查就会有所不同。无论如何,收到的参数只是文件名(即test.png),而不是整个路径。我假设cgi脚本现在是默认路径。如果您只是自己运行脚本来测试它,那么您可能不必太担心清理文件名。但是,在将其投入生产之前,请绝对确保已更改代码以正确处理文件名。正如proctor所说,您希望确保用户不能在文件名中包含目录。此外,print语句中存在XSS漏洞。如果用户提供的文件名为
“/>alert(“Hello”);如果您还没有提供,请打开Perl的污染模式。这并不完美,但总比没有好。实际上,无法从外部调用脚本,输出只是一个立即检查图像的小测试,事实上,PNG将从更大的位置打开(当然也是安全的)网页^^那台服务器上还有其他用户吗?创建图像的是graph方法,我不认为我可以告诉他在画布上创建图像或临时的东西。无论如何,即使我找到了这样做的方法,我怎么能显示图像呢?顺便提一下,这只是好奇,我需要存储图像。你应该在一个单独的调用。想想HTTP是如何工作的:具有单独URL的所有内容都在一个单独的调用中检索,因此您可以在调用到来时创建它。
sub WashFilename {
    use File::Basename;
    my $basename = basename( shift );
    # untainted , only use a-z A-Z 0-9 and dot
    $basename = join '', $basename =~ m/([.a-zA-Z0-9])/g;
    # basename is now, hopefully, file.ext
    ## so to ensure uniqueness, we adulterate it :)
    my $id = $$.'-'.time;
    my( $file, $ext ) = split /\./, $basename, 2 ;
    return join '.', grep defined, $file, $id, $ext;
} ## end sub WashFilename