HackThisSite - Extended Basic Mission 8

Challenge

Bill Gates wrote a Perl script that grants access to the company records; it has a security flaw that lets everyone in. Fix the flaw.

Bill Gates 写了个 Perl 脚本,用来校验访问者有没有权限读取公司记录;这段脚本存在安全缺陷,任何人都能拿到记录。要求把缺陷修掉。

1
2
3
4
5
6
7
8
#!/usr/bin/perl
chomp ( my $User = `/usr/bin/whoami` ) ;
print "Checking your access level...\n" ;
if ( $User == 'BillGates' ) {
print "Authorized! Here are the company records:\n" . `cat /home/BillGates/CompanyRecords.db` ;
die ( "Closing...\n" ) ;
}
die ( "You're not authorized!\n" ) ;

Solution

脚本的逻辑很短:用反引号执行 /usr/bin/whoami 拿到当前用户名存进 $User,然后只有一个 if 决定是否读取 /home/BillGates/CompanyRecords.db。要修好缺陷,改动点必然落在这个比较上;其它行(chompprintdie)都只是输出,不参与授权判断。

Perl 有两套比较运算符,不能混用:

  • ==!=<>数值比较,会先把两侧操作数转成数字;
  • eqneltgt字符串比较,逐字符对比。

脚本用的是 $User == 'BillGates'。两侧都是字符串,却在走数值比较。用 Perl 直接复现这个语义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/perl
# Local reproduction of the ExtBasic 8 flaw (run against our own Perl, no
# network). A non-privileged user name stands in for the whoami output.
use strict;
use warnings;

my $User = "some_user"; # what `/usr/bin/whoami` would return

my $target = "BillGates";

print "user : $User\n";
print "target : $target\n";
print "num(user) : ", $User + 0, "\n";
print "num(target): ", $target + 0, "\n";
printf "flawed \$User == \$target -> %s\n", ($User == $target) ? "TRUE" : "FALSE";
printf "fixed \$User eq \$target -> %s\n", ($User eq $target) ? "TRUE" : "FALSE";
1
2
3
4
5
6
7
8
9
$ perl -w perl_demo.pl
Argument "some_user" isn't numeric in addition (+) at perl_demo.pl line 13.
Argument "BillGates" isn't numeric in addition (+) at perl_demo.pl line 14.
user : some_user
target : BillGates
num(user) : 0
num(target): 0
flawed $User == $target -> TRUE
fixed $User eq $target -> FALSE

Perl 把非数字开头的字符串转成数字时取前导数字部分,没有前导数字就是 0(同时抛 isn't numeric 警告)。whoami 返回的是用户名,BillGates 也是裸字符串,两者的数值转换结果都是 0

授权条件退化成 0 == 0,恒为真。任何用户名(rootnobody、普通用户都一样)都会走进 if 分支,打印记录再 die("Closing...")。真正的字符串判定应该用 eq'some_user' eq 'BillGates' 为假,只有用户名恰好是 BillGates 时才通过。

if ($User eq BillGates)