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 脚本,用来校验访问者有没有权限读取公司记录;这段脚本存在安全缺陷,任何人都能拿到记录。要求把缺陷修掉。
关卡把整段脚本放在 <pre> 里,正文说明是
Fix the flaw for him!:
1 | #!/usr/bin/perl |
页面底部的提交表单指向
/missions/extbasic/template.php,字段是
formkey(每次加载关卡页都换值)、lvl=8 和
pass:
1 | <form action="/missions/extbasic/template.php" method="post"> |
Solution
脚本的逻辑很短:用反引号执行 /usr/bin/whoami
拿到当前用户名存进 $User,然后只有一个 if
决定是否读取
/home/BillGates/CompanyRecords.db。要修好缺陷,改动点必然落在这个比较上;其它行(chomp、print、die)都只是输出,不参与授权判断。
Perl 有两套比较运算符,不能混用:
==、!=、<、>:数值比较,会先把两侧操作数转成数字;eq、ne、lt、gt:字符串比较,逐字符对比。
脚本用的是
$User == 'BillGates'。两侧都是字符串,却在走数值比较。用
Perl 直接复现这个语义:
1 | #!/usr/bin/perl |
1 | $ perl -w perl_demo.pl |
Perl 把非数字开头的字符串转成数字时取前导数字部分,没有前导数字就是
0(同时抛 isn't numeric
警告)。whoami 返回的是用户名,BillGates
也是裸字符串,两者的数值转换结果都是 0。
授权条件退化成
0 == 0,恒为真。任何用户名(root、nobody、普通用户都一样)都会走进
if 分支,打印记录再
die("Closing...")。真正的字符串判定应该用
eq:'some_user' eq 'BillGates'
为假,只有用户名恰好是 BillGates 时才通过。这正是标题里
VisualBasic 转 Perl 的讽刺:VB 里 = 依赖类型推断,搬到 Perl
用错运算符就成了全局绕过。
只改这一处比较运算符,其余原文照抄:
1 | if ( $User eq 'BillGates' ) { |
提交的是这一行修正后的语句(== →
eq)。取页面拿 formkey、POST、再读回关卡页与
profile 的完整脚本:
1 | #!/usr/bin/env python3 |
运行输出:
1 | $ cd <hts-workspace> && uv run python challenges/hts-playit/extbasic-8/solve.py --answer "if ($User eq 'BillGates')" --tag cand1 |
服务端对这条修正给出下一关的 go on
链接,这是被接受的判据:
1 | <br /><a href='/missions/playit/extbasic/9'><img src='http://hackthissite.org/missions/GoOn.gif' alt='go on' title='go on' border='0'/></a><!--TY tormn for the go on pic--></td> |
Key points
- Perl 里数值比较与字符串比较是两套运算符:
==/eq、!=/ne,拿字符串去走==会触发类型强制转换 - 非数字开头的字符串转数字得到
0并抛isn't numeric警告;两个不同的裸字符串用==比较就退化成0 == 0 - 修复只动比较运算符:
$User == 'BillGates'→$User eq 'BillGates',其它行保持不变 - 提交必须带
Referer: /missions/playit/extbasic/8/,且formkey每次加载页面都变,取页面与提交要在同一次运行内完成