HackThisSite - ExtBasic Mission 05
Challenge
ExtBasic Mission 05 — fix the broken line in a shell script that is supposed to patch a PHP page. 修正 Sam 用来修补 PHP 页面的 shell 脚本里被写错的那一行。
关卡给出一个 PHP 页面:本该调用 safeeval()
包装函数的地方,写成了裸的 eval()。
1 |
|
Sam 写了个 shell 脚本,用 sed 把 eval
批量改写成 safeeval:
1 |
|
页面说明 Sam 的系统是
freeBSD 6.9,顶部横幅另外提醒:不要写
sed -r,那是 Linux/GNU 专属,BSD 上要用
sed -E。
任务是修正 shell 脚本里写错的那一行(保持相同空格)。
Solution
横幅专门提醒 -r 与 -E
的区别,说明出题人预期玩家会先怀疑 sed 标志。脚本里已经是
sed -E,在 FreeBSD
上语法合法。这一行的问题不在方言,而在替换命令本身。
s/eval/safeeval/ 没有写全局标志
g:
- 不带
g:sed 对每一行只替换第一个匹配; - 带
g:替换行内所有匹配。
exec.php 里有不止一处
eval(($_GET['cmd'] 与
$_GET['cmd2'] 各一处),要一次全改掉,替换命令必须是
s/eval/safeeval/g。替换串 safeeval 本身含有
eval,但 sed
命中一次后从替换文本之后继续扫描,不会把刚写进去的 safeeval
再改一遍,所以加 g 不会破坏结果。
题目要求使用相同的空格,即整行照抄,只在正确的位置补上
g:
1 | sed -E "s/eval/safeeval/g" <exec.php >tmp && touch OK |
脚本其余部分不动,其写回保护依然成立:rm OK
清掉上一次的成功标记,&& touch OK 只在 sed
成功时创建标记,if [ -f OK ] 成立才执行
rm exec.php && mv tmp exec.php,避免半成品覆盖原文件。
formkey
每次加载页面都会变,取页面和提交必须在同一次运行里完成,脚本从环境变量读
cookie。
1 | import os |
Key points
- sed 的
g控制行内全部替换还是只替换首个匹配,是字符串改写式过滤/修复里最常见的静默缺陷 -E(BSD)与-r(GNU)不可互换,跨平台脚本要按目标 uname 选方言- sed 替换从左向右、不重叠扫描:
s/eval/safeeval/g不会二次命中刚生成的safeeval - 用
rm OK/touch OK标记配合&&,让写回原文件只在 sed 成功时发生