这是我的计算机安全课程的作业,所以我不需要具体的答案,但我想要一些建议或至少大方向,因为我已经进入了一段时间。
基本上,我们有一个任务,我们已经给了一个简单的cgi应用程序(用perl编写),它有一个允许用户查看私有文件的漏洞,比如/ etc / shadow,它们不应该是。我们基本上必须表明我们可以攻击它并查看/ etc / shadow文件。该应用程序是一个备忘录查看程序,允许用户编写和阅读备忘录。
现在,我对Perl很新。很久以前,我曾经使用过一次或两次非常简单的网页内容,但这确实是基础知识。
有问题的代码
#!/usr/bin/perl -w
use CGI qw(:standard);
use CGI::Carp qw(fatalsToBrowser);
use strict;
my %labels; # global of pretty labels for memo pathnames
# glob through the homedirs for an array of paths to memos sorted by date
sub list_memo_selector {
my @memos = </home/*/memo/*>; # all regular users
push (@memos, </root/memo/*>); # special memos from root
foreach (@memos) {
$_ =~ m#^.+/([^/]+)$#; # regex extract filename
my $temp = $1;
$temp =~ s/_/ /g; # convert _ to " "
$labels{$_} = $temp; # assign pretty label name
}
print popup_menu(-name=>'memo', -values=>\@memos, -labels=>\%labels);
print submit("Read memo");
}
print header();
print "<html><head><title></title></head><body>\n";
print h1("FrobozzCo Memo Distribution Website");
print h4("Got Memo?");
print hr();
print p('Select a memo from the popup menu below and click the "Read memo" button.');
print p("<form method='post' name='main'>\n");
if (!param('memo')) {
list_memo_selector();
} else { # there is a memo selected
list_memo_selector();
my $memo = param('memo');
my $author = "root";
my @stat = stat $memo;
my $date = localtime $stat[9];
if ($memo =~ m#^/home/([^/]+)/.*$#) {
$author = $1;
}
print "<hr>\n";
print "<blockquote>";
print '<table border=1><tr><td>';
print "<center><b>$labels{$memo}</b></center>";
print '</td></tr>';
print "<tr><td>\n<p>";
print "<b>Author:</b> $author<br />\n";
print "<b>Subject:</b> $labels{$memo}<br />";
print "<b>Date:</b> $date<br />\n";
print "\n</p></td></tr>\n";
print "<tr><td><p> </p>\n";
print "<blockquote><p>\n";
open (MEMO, $memo);
foreach (<MEMO>) {
$_ =~ s#\n$#</p><p>#; # HTMLize newlines for formatting
print "$_\n";
}
print "</p></blockquote>\n";
print '<p> </p></td></tr></table>';
print "</blockquote>";
print "<hr>\n";
}
print h2("To publish a memo:");
print <<TEXT;
<ol>
<li>Create a directory named 'memo' in your home directory.</li>
<li>Edit text files in that directory.</li>
<li>Save the file using underscores (_) for spaces, e.g. "free_lunch".</li>
</ol>
TEXT
print p('To remove your memo from publication, simply delete the file from tme memo directory.');
print "</form>\n";
print "</body></html>";
我认为关键是程序调用open(MEMO,$ memo)而不检查用户的输入,所以如果你可以将它指向/ etc / shadow,程序就会打印出shadow文件。
问题是,目前它只列出home / * / memo或/ root / memo中的文件。我一直试图弄清楚如何指向其他地方。我认为这与我们可以创建自己的备忘录(通过在homedir中创建一个名为memo的目录)这一事实有关。但我无法弄清楚我需要在备忘录中放置什么来让程序打开/ etc / shadow。
有人知道我是在正确的轨道上还是完全错过了另一个明显的错误?
答案 0 :(得分:4)
你错过了明显的错误。
创建一个弹出菜单以指定memo
值,但没有任何内容强制用户仅指定其中一个预先填充的值。他们可以指定任何东西。
甚至没有执行POST请求方法,因此在URL中编辑表单参数就足以指定一个值:
http://www.yourdomain.com/form.cgi?memo=/etc/naughty/boy
<强>验证强>
为了避免攻击,必须通过以下任一方式验证数据是否在我们预期的值范围内:
引入新bug的可能性最小的是重用原始值。这是因为很容易使正则表达式变得不够严格。例如,允许updir ..
包含在某个路径中。
此外,open
调用应该使用3参数形式以及词法文件句柄,而我们在此处。我们不希望允许用户指定打开文件的模式。
open my $fh, '<', $memo or die "Can't open $memo: $!";