缓冲区溢出导致终端将额外的字符作为 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
来提供帮助,该函数不会从该文件中消耗比您请求更多的字节。对比基于流的函数,例如 fread
、fgets
和 scanf
,它们最常执行 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 的控制终端的人或程序才能向其提供输入。您没有证明其他情况。没有特别的安全考虑要讨论。
我开始接受 缓冲区溢出 风险,尤其是涉及低级 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 theread
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
来提供帮助,该函数不会从该文件中消耗比您请求更多的字节。对比基于流的函数,例如 fread
、fgets
和 scanf
,它们最常执行 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 的控制终端的人或程序才能向其提供输入。您没有证明其他情况。没有特别的安全考虑要讨论。