首页 > 解决方案 > 缓冲区溢出导致终端作为 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>

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

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

标签: csecurityiolimitbuffer-overflow

解决方案


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

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

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

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

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

非控制台程序执行情况如何,例如GUI 应用程序Web 应用程序等......在这种情况下它们会如何表现?最重要的是,在二进制利用和代码注入方面,以及我不知道的其他安全方面,这种情况会引发哪些安全问题?

只有直接访问程序的父 shell(如果有)或该 shell 的控制终端的人或程序可以向其提供输入。你没有另外证明。没有特别的安全考虑要讨论。


推荐阅读