这是我的计算机安全课程的作业,所以我不需要具体的答案,但我想要一些建议,或者至少是总体方向,因为我已经绕了一段时间了。
基本上,我们有一个任务,给我们一个简单的 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>";
Run Code Online (Sandbox Code Playgroud)
我认为关键是程序调用 open(MEMO, $memo) 而不检查用户的输入,因此如果您可以将其指向 /etc/shadow 程序只会打印出影子文件。
问题是,目前它只列出 home/*/memo 或 /root/memo 中的文件。我一直在试图弄清楚如何指向其他地方。我认为这与我们可以创建自己的备忘录(通过在我们的 homedir 中创建一个名为 memo 的目录)这一事实有关。但我不太清楚需要在备忘录中放入什么内容才能让程序打开 /etc/shadow 。
有谁知道我是否走在正确的轨道上或完全错过了另一个明显的错误?
你错过了明显的错误。
创建弹出菜单来指定memo
值,但没有任何内容强制用户仅指定预填充值之一。他们可以指定任何内容。
甚至没有强制执行 POST 请求方法,因此编辑 URL 中的表单参数就足以指定值:
http://www.yourdomain.com/form.cgi?memo=/etc/naughty/boy
Run Code Online (Sandbox Code Playgroud)
验证
为了避免攻击,必须通过以下任一方式验证数据是否在我们预期的值范围内:
最不可能引入新错误的方法是重用原始值。这是因为很容易使正则表达式限制不够。例如,允许 updir..
包含在路径中的某处。
此外,open
调用时应使用 3 参数形式以及词法文件句柄。我们不想让用户指定打开文件的模式。
open my $fh, '<', $memo or die "Can't open $memo: $!";
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1928 次 |
最近记录: |