【问题标题】:Setting up SUID in C language is not enough用 C 语言设置 SUID 是不够的
【发布时间】:2021-01-06 12:30:13
【问题描述】:

出于教学目的,我想在 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,我认为这已经足够了,但显然不是。我在这里错过了什么?

【问题讨论】:

    标签: c security debian code-injection


    【解决方案1】:

    作为system() 调用的一部分执行的/bin/sh 正在删除特权。请参阅 bash 的手册页和 -p 选项

    如果 shell 启动时有效用户(组)id 不相等 到真实的用户(组)ID,并且没有提供 -p 选项,没有 启动文件被读取,shell 函数不继承自 环境、SHELLOPTS、BASHOPTS、CDPATH 和 GLOBIGNORE 变量,如果它们出现在环境中,将被忽略,并且 有效用户标识设置为真实用户标识。如果 -p 选项是 在调用时提供,启动行为是相同的,但 有效用户 ID 不会重置。

    嗯,从技术上讲,debian 默认使用dash,但它做同样的事情。

    因此,shell 的默认行为已被调整以至少在一定程度上减轻这种注入。

    【讨论】:

    • 注意:你可以自己看到它是通过在 strace 下运行整个事情来完成的(以 root 身份启动,strace -f su - olive ...)
    猜你喜欢
    • 1970-01-01
    • 2012-08-19
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 2017-01-15
    • 2016-06-19
    • 2021-01-31
    相关资源
    最近更新 更多