C语言 缓冲区溢出导致终端作为 shell 命令执行额外的字符



我开始缓冲溢出风险,尤其是在涉及低级 C 库输入/输出函数并试图了解它与内存利用代码注入的关系时。

我正在考虑以下代码块及其执行给出的奇怪行为:

int main ()
{
char buffer[10];
int r = read (STDIN_FILENO, buffer, 14);
puts(buffer);
return EXIT_SUCCESS;
}

现在,当给定以下 17 大小的输入时

Hello, World !pwd

我得到以下输出:

Hello, Wor
> pwd
/media/...<current working directory path>

如输出所示,3 个额外的字符(此处有意pwd用于演示目的( - 超出read函数的指定限制 - 被终端接管并作为 shell 命令执行。

低层次的角度来看,是什么导致了这种行为?
可以用来执行代码注入吗?

如输出所示,3 个额外的字符(此处有意pwd出于演示目的( - 这是越界的read函数的指定限制 - 被终端接管 并作为 shell 命令执行。

低层次的角度来看,这怎么可能?

正如@ChrisTurner首先在评论中观察到的那样,在程序退出后,pwd被解释为启动程序的 shell 的输入也就不足为奇了。 尽管每个程序都有自己的句柄,但它们正在从同一个文件读取,可能连接到终端。

但是,您的程序通过使用低级 I/O 函数read会有所帮助,该函数不会消耗比您请求的更多的字节。 对比基于流的函数,如freadfgetsscanf,它们最常执行缓冲读取(这是它们操作的流的特征,而不是函数本身(。 在您的特定情况下,其中任何一个都会消耗所有输入,包括第一个换行符。

您的程序中确实存在潜在的缓冲区溢出,但这是一个红鲱鱼。 您描述的行为确实取决于读取请求的完整 14 字节read,这不能保证这样做,但出于所有意图和目的,当标准输入连接到终端时,您可以依靠它来执行。 这样做了,你的程序确实会表现出未定义的行为,但该 UB 的表现可能会被限制在程序的输出上(注意它是如何被截断的?(甚至对你来说是不可见的。 它不负责将"pwd"读取为父 shell 的输入。

怎么样 非控制台程序执行,如GUI 应用程序Web 应用程序等... 在这种情况下,他们会如何表现?最重要的是,什么 这种情况是否在二进制方面引发安全问题利用和代码注入,也许还有其他安全方面 我不知道 ?

只有直接访问程序的父 shell(如果有(或该 shell 的控制终端的个人或程序才能向其提供输入。 你没有证明其他。 没有要讨论的特定安全注意事项。

最新更新