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>
如输出所示,pwd
超出read
函数指定限制的 3 个额外字符(此处为演示目的)被终端接管并作为 shell 命令执行。
从低层次的角度来看,是什么导致了这种行为?
可以用来进行代码注入吗?
解决方案
如输出所示,
pwd
超出read
函数指定限制的 3 个额外字符(此处为演示目的)被终端接管并作为 shell 命令执行。从低层次的角度来看,这怎么可能?
正如@ChrisTurner 在评论中首先观察到的pwd
那样,在程序退出后,将其解释为启动程序的 shell 的输入并不令人惊讶。尽管每个程序都有自己的句柄,但它们是从同一个文件中读取的,可能连接到一个终端。
但是,您的程序通过使用低级 I/O 函数来提供帮助,read
该函数不会从该文件中消耗比您请求更多的字节。对比基于流的函数,例如fread
、fgets
和scanf
,它们最常执行缓冲读取(这是它们操作的流的特征,而不是函数本身)。在您的特定情况下,其中任何一个都会消耗所有输入,包括第一个换行符。
您的程序中确实存在潜在的缓冲区溢出,但这是一个红鲱鱼。您所描述的行为确实取决于read
读取请求的完整 14 个字节,但不能保证这样做,但出于所有意图和目的,当标准输入连接到终端时,您可以依靠它来完成。这样做之后,您的程序确实会表现出未定义的行为,但是该 UB 的表现可能会受限于程序的输出(注意它是如何被截断的?),甚至对您来说是不可见的。它不负责被父 shell 读取为输入的“pwd”。
非控制台程序执行情况如何,例如GUI 应用程序、Web 应用程序等......在这种情况下它们会如何表现?最重要的是,在二进制利用和代码注入方面,以及我不知道的其他安全方面,这种情况会引发哪些安全问题?
只有直接访问程序的父 shell(如果有)或该 shell 的控制终端的人或程序可以向其提供输入。你没有另外证明。没有特别的安全考虑要讨论。
推荐阅读
- flutter - 我的flutter应用程序热重启后注销,即使重启后也无法使应用程序保持登录状态
- javascript - 使用编码字符正确选择偏移
- netlify - Hugo / Blogdown 图片在 GitHub/Netlify 部署后无法渲染
- python - 使用 Python / 身份验证连接到 SharePoint
- javascript - reactjs 中的 ICryptoTransform 解密器 C# 等效项
- node.js - 使用 Mongoose 和 Express 连接到 MongoDB 时出现“主机标识符中的错误斜线”
- javascript - 三元运算符条件
- node.js - 在 NodeJS 本地服务器上编辑 JSON 文件导致“Express Session”参数设置为未定义
- javascript - 如何仅从图像 url 将图像发送到服务器?
- c - 如何使用 Make 将目标文件编译到存档中