C 缓冲区溢出导致终端以shell命令的形式执行额外字符

C 缓冲区溢出导致终端以shell命令的形式执行额外字符,c,security,io,limit,buffer-overflow,C,Security,Io,Limit,Buffer Overflow,我开始考虑缓冲区溢出风险,特别是在涉及低级C库输入/输出函数时,并试图了解它与内存利用和代码注入的关系 我正在考虑以下代码块及其执行所产生的奇怪行为: int main () { char buffer[10]; int r = read (STDIN_FILENO, buffer, 14); puts(buffer); return EXIT_SUCCESS; } 现在,当给出以下17个大小的输入时 你好,世界!pwd 我得到以下输出: Hello

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

我正在考虑以下代码块及其执行所产生的奇怪行为:

int main ()
{
     char buffer[10];

     int r = read (STDIN_FILENO, buffer, 14);
     puts(buffer);

     return EXIT_SUCCESS;
}
现在,当给出以下17个大小的输入时

你好,世界!pwd

我得到以下输出:

Hello, Wor
> pwd
/media/...<current working directory path>
你好,沃尔 >pwd /媒体/。。。 如输出所示,3个额外字符(此处为演示目的故意
pwd
)超出了
read
函数的指定限制,被终端接收并作为shell命令执行

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

如输出所示,3个额外字符(此处为
pwd
为了演示的目的)-这是不允许的
读取
功能的指定限制-被终端接管 并作为shell命令执行

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

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

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

您的程序中确实存在潜在的缓冲区溢出,但这是一种危险的做法。您描述的行为确实取决于读取请求的全部14个字节,但不保证这样做,但无论出于何种目的,当标准输入连接到终端时,您都可以依靠它来执行。如果这样做了,您的程序确实会表现出未定义的行为,但是UB的显示可能会被限制到程序的输出(注意它是如何被截断的?),甚至对您来说是不可见的。它不负责父shell将“pwd”读取为输入

那怎么办 非控制台程序执行,如GUI应用程序、web应用程序等。。。 在这种情况下他们会怎么做?最重要的是,什么 从二进制角度来看,这种情况会带来安全问题吗 利用漏洞和代码注入,可能还有其他安全方面 我不知道是什么


只有直接访问程序的父shell(如果有)或该shell的控制终端的人员或程序才能向其提供输入。你没有表现出其他方面。没有特别的安全考虑需要讨论。

堆栈溢出不是一个教程站点,这一点非常广泛(请参阅和)。找一本好书或一个教程网站。@Someprogrammerdude关于堆栈溢出的问题有很多非常相似的问题,甚至比这个问题更广泛、更技术。为什么会有这种奇怪的行为?您的代码读取14个字节,剩下的由shell读取,processUB代表未定义的行为。在这种情况下,通过溢出数组的边界(假设
读取
确实读取了完整的14个字节,这似乎是事实,但不能保证)。@JohnBollinger我想这是因为
r
缓冲区
之后声明,并设置为14Thanx以获得详细答案。因此,它与代码注入或内存利用几乎没有关系,如果我理解得很好的话?@programmersn,shell读取并执行程序输入端的“pwd”的结果与代码注入或内存利用无关。