Level 02——环境变量注入

详情:

以下程序中存在一个允许任意程序执行的漏洞,你能找到它吗?要执行此级别,请使用 level02 帐户和密码登录。此级别的文件位于 /home/flag02。

这关的程序存在一个可执行任意程序的漏洞,题目提供了完整的源码:

#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);
}

Solution:

在kali中通过ssh远程连接level02@nebula,以后就不再赘述了。

和第一关思路一样,我们先找到执行系统命令的函数——函数体的最后一句system,并且可以看到system执行的字符串来源于变量,那么就应该回溯buffer变量是怎么生成的。

可看到buffer变量是经过asprintf拼接而成,而asprintf的第二个参数调用了getenv函数去获取环境变量USER的值(USER是当前登录的用户名)。有了第一关的经验,我们就知道环境变量是依赖于外部控制,默认下,asprintf组合的最终结果是:/bin/echo level02 is cool

>asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));

的作用是:构造一个字符串 /bin/echo 用户名 is cool 并将其存入 buffer 中。


✅ 分解解释

getenv("USER")

  • 调用系统函数获取当前环境变量 USER 的值

  • 比如,如果当前登录用户是 ctfplayer,那么返回值是 "ctfplayer"


asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"))

  • asprintf 是一个格式化字符串函数,类似 sprintf,但会自动 分配内存buffer

  • 格式化字符串:"/bin/echo %s is cool",其中 %s 会被 getenv("USER") 的值替换

由于环境变量USER是可以控制的,所以可以把USER变量替换掉。USER变量如果换成;bin/getflag,等于是在执行了以下两句:(执行多条命令用”;”隔开)

/bin/echo;
/bin/getflag

image-20250602193915656