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

Buffer overflow causes extra characters to be executed by terminal as shell command

我开始接受 缓冲区溢出 风险,尤其是涉及低级 C 库 input/output 函数并试图了解它与内存利用代码注入

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

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>

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

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

As shown by the output, the 3 extra characters (here intentionally pwd for demonstration purposes) - that were out of bounds for the specified limit of the read function - got taken over by the terminal and executed as a shell command.

How is that possible, from a low-level perspective ?

正如@ChrisTurner 在评论中首先观察到的,在程序退出后,pwd 被解释为您启动程序的 shell 的输入,这并不奇怪。虽然每个程序都有自己的句柄,但它们正在读取同一个文件,可能连接到终端。

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

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

读取为输入

What about non-console program execution, like GUI apps, web apps, and so on ... How would they behave in this case ? And most importantly, what security issues does this situation raise, in terms of binary exploitation and code injection, and maybe other security aspects that I'm not aware of ?

只有能够直接访问程序的父级 shell(如果有)或 shell 的控制终端的人或程序才能向其提供输入。您没有证明其他情况。没有特别的安全考虑要讨论。