出于教学目的,我想在C中设置一个基本的命令注入。我有以下代码:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv) {
char cat[] = "cat ";
char *command;
size_t commandLength;
commandLength = strlen(cat) + strlen(argv[1]) + 1;
command = (char *) malloc(commandLength);
strncpy(command, cat, commandLength);
strncat(command, argv[1], (commandLength - strlen(cat)) );
system(command);
return (0);
}
我编译它,将二进制文件设置为root所有,并将SUID设置为1,如下所示:
gcc injectionos.c -o injectionos
sudo chown root:root injectionos
sudo chmod +s injectionos
我得到以下结果:
ls -la
total 40
drwxr-xr-x 2 olive olive 4096 Jan 6 13:17 .
drwxr-xr-x 3 olive olive 4096 Jan 6 12:15 ..
-rwsr-sr-x 1 root root 16824 Jan 6 13:17 injectionos
-rw-r--r-- 1 olive olive 415 Jan 6 13:17 injectionos.c
-rwx------ 1 root root 9 Jan 6 12:43 titi.txt
-rw-r--r-- 1 olive olive 9 Jan 6 12:16 toto.txt`
因此,基本上,在SUID设置为1的情况下,我应该能够通过执行以下注入来打开toto.txt和titi.txt文件:
./injectionos "toto.txt;cat titi.txt"
但是执行这个命令时,我在访问titi.txt时得到了一个permission denied
。最后,当我在代码中添加setuid(geteuid());
时,注入正在工作,我可以访问titi.txt文件。
考虑到injectionos是作为root运行的,titi.txt属于root,我认为这已经足够了,但显然没有。我在这里缺少什么?
作为system()
调用的一部分执行的/bin/sh
正在删除特权。参见bash和-p
选项的手册页
如果shell是在有效用户(组(id不相等的情况下启动的到真实的用户(组(id,并且没有提供-p选项,否启动文件是读取的,shell函数不是从环境、SHELLOPTS、BASHOPTS、CDPATH和GLOBIGNORE变量(如果出现在环境中(将被忽略,并且有效用户id设置为真实用户id。如果-p选项为在调用时提供,启动行为是相同的,但未重置有效的用户id。
从技术上讲,debian默认使用dash
,但它也做同样的事情。
因此,shell的默认行为已经进行了调整,至少在一定程度上减轻了这种注入。