WeChall - Choose your Path
Challenge
This is the level10 mini challenge found in
/home/level/10/on the warchall box. You can view the source here. 这是 Warchall 服务器上的 Level 10 小挑战,目录在/home/level/10/(当前服务器实际目录名为/home/level/10_choose_your_path/),题目页面给出了源码。
题目程序 charp
会统计一个文件的平均每行字符数。源码核心逻辑如下:
1 |
|
目录里有两个关键文件:
1 | $ ls -la /home/level/10_choose_your_path/ |
solution.txt 对普通用户不可读,但 charp 有
setgid bit:执行时有效 group 变成
level10,所以它能读这个文件。
Solution
关键约束:
- 程序确实用绝对路径
/usr/bin/wc,所以不能通过PATH劫持wc。 - 但它把用户输入的
filename直接拼进 shell 命令,再交给popen()执行。 popen()等价于让/bin/sh -c执行字符串,因此;,|,#, redirection 都会被 shell 解析。
也就是说,这不是文件路径选择问题,而是 command injection。
程序第一次执行的命令形如:
1 | /usr/bin/wc -l <filename> |
如果我们把 <filename> 传成:
1 | solution.txt 1>&2; /bin/cat solution.txt 1>&2; # |
实际命令会变成:
1 | /usr/bin/wc -l solution.txt 1>&2; /bin/cat solution.txt 1>&2; # |
解释:
solution.txt作为正常参数,让wc不至于立刻失败。1>&2把 stdout 重定向到 stderr。charp会从popen()的 stdout 里读取数字;如果把注入命令的输出留在 stdout,可能干扰fscanf()。; /bin/cat solution.txt 1>&2追加执行cat,借助 setgid 权限读取答案,并输出到 stderr。#注释掉后面可能拼接出的残余命令片段。
Live 验证命令:
1 | $ ssh -p 19198 <username>@warchall.net |
输出会出现两次,是因为程序先执行 wc -l,再执行
wc -c,两次 popen() 都会拼接同一个
filename,所以注入的 cat solution.txt
也被执行两次。