https://www.root-me.org/fr/Challenges/App-Script/ELF32-System-1
根据题意,我们的目标是查看/challenge/app-script/ch11/.passwd中的密码。
在ssh连接到的终端上:
首先, ls -l 查看文件及其权限,我们看到:
-r-sr-x--- 说明可执行文件 ch11 在执行时可获取root权限。(这里需要了解real user id, effective user id 和 saved user id, 可参考https://www.itread01.com/p/1387916.html;以及了解setreuid()函数,可参考https://blog.csdn.net/hittata/article/details/8670208)
cat ch11.c 可看到ch11.c的内容,即为题目中的代码:
如果直接使用 cat 查看/challenge/app-script/ch11/.passwd 是没有root权限的:
解题思路为:
既然ch11程序拥有root权限,那么如果将代码中的ls替换成cat,就可以查看。然而作为普通用户,对ch11.c没有写权限,所以不能修改c代码。即使可以修改,也没有Makefile的执行权限。
那么我们可以通过修改环境变量PATH,使ls命令实际上执行的是/bin/cat命令。
第一步,将/bin/cat命令复制到/tmp/test/ls:
cp /bin/cat /tmp/test/ls
(注:1. /tmp/ls已存在,不可更改。2. 只有/tmp有写权限,所以将其放在/tmp下。)
第二步,修改环境变量,添加路径/tmp/test:
export PATH="/tmp/test:$PATH"
现在代码中的ls将会执行/tmp/test/ls,实际上就是/bin/cat,而不是执行原先的/bin/ls。
执行./ch11,密码就会在终端显示出来了。
作为新手,我还有几个问题有待弄明白:
1. 既然-r-sr-x---文件已经有执行时的root权限了,为何代码中还需要有setreuid()?
经本地linux实验,如果删除文件中的setreuid(),那么程序将没有root权限。结合之前关于user id的知识推测:
chmod u+s只是saved uid (suid) = owner uid,执行时还需使用setreuid(geteuid(), geteuid()),使real uid = effective uid = saved uid,其中geteuid()返回的就是saved uid的值, 此处若不使real uid = saved uid, 程序也没有root权限。这很奇怪,按理说程序执行时只看effective uid。有待考证,若有高人望予指点。
2. 普通用户修改环境变量真的也会改变root用户的环境变量吗?
并不会。
1. 每次打开shell终端,它会加载profile和bashrc文件中的变量。export只改变当前shell的环境变量。
2. 环境变量具有继承性。我们的题目中system(const char *cmd)函数会先调用/bin/sh命令创建一个shell进程,然后让该shell进程运行传入的cmd命令[2]。因为此shell进程会继承其父进程shell的环境变量。
- 经验教训:
引用挑战页面链接的文章:
[1] “Dangers of SUID Shell Scripts"
http://repository.root-me.org/Administration/Unix/EN%20-%20Dangers%20of%20SUID%20Shell%20Scripts.pdf
[2] "Set-UID Privileged Programs"
- (被)Set-UID的程序需要注意一些环境变量:
1. PATH:命令路径目录
编程时应指明命令的绝对路径,比如题目中ls应写作/bin/ls。
2. IFS:转义为空格的字符
目前IFS被大多数的shell禁用,子进程也不继承IFS。
3. LD_LIBRARY_PATH: 动态链接库文件路径目录
目前,Set-UID程序链接库文件时会忽略LD_LIBRARY_PATH。安全的程序应设置链接库文件的路径为静态路径。
4. LD_PRELOAD:预先载入库文件路径
目前,Set-UID root程序链接库文件时会忽略LD_PRELOAD,除非real uid也等于0。
(具体例子参考[2])
- 此外,还需注意set-uid程序中system(cmd)的使用,不验证用户的输入参数可使被system()调用的shell执行其他命令。
比如:
// The contents of User_Input are provided by users.
sprintf(command, "/bin/mail %s", User_Input);
system(command);
当用户输入xyz@example.com ; rm -f /* ; /bin/sh时,其它命令被执行。
[2]中还有其他一些命令的漏洞将在另一篇文章中讨论。
[2]中还提到如何改进set-uid程序的安全性以及最小权限原理(Principle of Least Privilege),也在另一篇文章中阐述。


没有评论:
发表评论