安全地使用临时文件

在我的程序中有一个静态库,它只能把文件名作为input,而不是实际的文件内容。 对于图书馆的源代码,我无能为力。 所以我想:创build一个全新的文件,将数据存储到它中,将其刷新到磁盘(?),将其名称传递给库,然后删除它。

但我也希望这个过程相当安全:
1)文件必须重新创build,没有任何虚假的数据(也许它不是关键,但无论如何);
2)除了我的进程之外,任何人都不能读/写这个文件(我希望库能够处理我的实际数据,而不是一些聪明的插件)。
3)我完成这个文件后,它必须被删除(好的,如果有人TerminateProcess()我,我猜没有什么可以做的,但仍然)。

该库似乎使用非Unicode fopen()来打开给定的文件,所以我不太清楚如何处理所有这些,因为该程序旨在运行在Windows上。 有什么build议么?

你已经有了很多建议,但另一个我不认为已经提到的选项是使用命名管道。 这将取决于图书馆是否有效,但可能值得一试。 您可以使用CreateNamedPipe函数在您的应用程序中创建一个命名管道,并将管道的名称传递给库进行操作(您将传递的文件名将是\\。\ pipe \ PipeName )。 图书馆是否接受这样的文件名是你必须尝试的,但是如果它有效的话,你的文件永远不必写入磁盘。

这可以通过使用CreateFileGetTempFileName函数来实现(如果您不知道是否可以写入当前工作目录,也可能需要使用GetTempPath )。

  1. 确定一个目录来存储你的临时文件; 当前目录(“。”)或GetTempPath的结果将是不错的选择。
  2. 使用GetTempFileName来创建一个临时文件名称。
  3. 最后,调用CreateFile来创建临时文件。

最后一步,有几件事情要考虑:

  • CreateFiledwFlagsAndAttributes参数应该包含FILE_ATTRIBUTE_TEMPORARY
  • dwFlagsAndAttributes参数可能还应该包含FILE_FLAG_DELETE_ON_CLOSE ,以确保文件被删除,无论如何(这可能也适用于您的进程崩溃,在这种情况下,系统将关闭您的所有句柄)。
  • CreateFiledwShareMode参数可能应该是FILE_SHARE_READ以便其他尝试打开文件将成功,但仅用于阅读 。 这意味着你的库代码将能够读取文件,但是没有人能够写入它。

本文应该给你一些关于这个问题的很好的指导。

这件事的要点是:

  • POSIX mkstemp()函数是可用的安全且首选的解决方案。 不幸的是,它在Windows中不可用,所以你需要找到一个使用Windows API调用来正确实现这个功能的包装器。
  • 在Windows上, tmpfile_s()函数是唯一一个实际以原子方式打开临时文件(而不是简单地生成文件名)的功能,可以保护您免受竞争条件的影响。 不幸的是,这个函数不允许你指定文件将被创建到哪个目录,这是一个潜在的安全问题。

主要的,你可以在用户的​​临时文件夹中创建文件(例如C:\ Users \\ AppData \ Local \ Temp) – 这是一个完美的地方。 其次,在创建文件时 ,您可以指定您提供什么样的访问共享。

MSDN上CreateFile帮助页面的片段:

dwShareMode

  • 0防止其他进程在请求删除,读取或写入访问时打开文件或设备。
  • FILE_SHARE_DELETE启用文件或设备上的后续打开操作来请求删除访问。 否则,其他进程如果请求删除访问,则不能打开该文件或设备。 如果未指定此标志,但文件或设备已被打开以进行删除访问,则该功能失败。 注意:删除访问权限允许删除和重命名操作。
  • FILE_SHARE_READ启用文件或设备上的后续打开操作来请求读取访问。 否则,如果其他进程请求读取访问权限,则不能打开该文件或设备。 如果未指定此标志,但文件或设备已被打开以进行读取访问,则该功能将失败。
  • FILE_SHARE_WRITE使文件或设备上的后续打开操作能够请求写入访问。 否则,如果其他进程请求写访问权限,则不能打开该文件或设备。 如果未指定此标志,但文件或设备已被打开以进行写入访问或具有写入访问的文件映射,则该功能将失败。

虽然给出的建议是好的,如使用FILE_SHARE_READ,FILE_DELETE_ON_CLOSE等,我不认为有一个完全安全的方法来执行。

我已经使用过程资源管理器来关闭文件,目的是为了防止第二个进程的启动 – 我这样做是因为第一个进程卡住了,并且“不能杀死,没有死,但没有响应”,所以我有一个合理的理由做到这一点 – 由于系统上运行的其他进程,我不想在该特定点重新启动机器。

如果有人使用某种类型的调试器(包括非商业的,专为此目的而编写的),附加到正在运行的进程,设置断点并停止代码,然后关闭已打开的文件,可以写入文件你刚创建。

你可以使它更难,但是你不能阻止有足够的特权/技能/能力的人拦截你的程序和操纵数据。

请注意,如果您确实知道用户在计算机上没有特权帐户,则文件/文件夹保护功能才起作用 – 典型的Windows用户要么是管理员,要么是为了管理目的而拥有另一个帐户 – 并且可以访问sudo / root几乎所有在工作中使用的Linux机器 – 有一些文件服务器,我没有(也不应该)有root权限。 但是我自己使用的所有框或者可以借用测试目的,我可以到达根环境。 这不是很不寻常。

我能想到的解决方案是找到一个不同的库,使用不同的接口[或获取库的来源和修改,以便它]。 并不是说这样做可以防止使用上述调试器方法进行“停止,修改和继续”攻击。

使用CreateFile API在您的可执行文件的文件夹中创建您的文件,您可以给文件名称一些UUID,每次创建它,以便其他进程不能猜测文件名称来打开它。 并将其属性设置为隐藏。 使用之后,只需删除文件即可