写入文件并以原子方式执行



假设我在内存中有一个可执行文件(或bat脚本,无关紧要(的内容,并希望将其作为一个新进程运行。这很容易。

File.WriteAllBytes(filePath, contents);
// gap
Process.Start(filePath)

但我想确保执行的文件不会被任何其他进程篡改。文件的创建和执行之间存在差距。它提供了一个用正确的工具篡改文件的机会。

因此,我不再使用File.WriteAllBytes,而是打开FileStreamFileShare.Read,并将其保持打开状态,直到执行完成。

using(var fileStream = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
{
Process.Start(filePath)
}

但这行不通。Process.Start失败:

System.ComponentModel.Win32Exception(32(:进程无法访问该文件,因为另一个进程正在使用该文件。

这个问题及其答案解释了我为什么这么想。简而言之,Process.Start将尝试用FileShare.Read打开文件,但由于打开的FileStream已经具有写访问权限,因此失败了进程的FileShare.Read尝试。

有没有干净的方法?

我能想到的一个解决办法是保存文件,关闭它,用FileShare.ReadFileAccess.Read打开一个新的FileStream,确保内容在执行之前保持不变。但这并不好看。

您所描述的是检查时间到使用时间漏洞的典型案例。

任何涉及检查某个内容然后执行它的解决方案,如果这两个操作不是原子操作,仍然会使您处于易受攻击的状态。例如:

在执行之前确保内容仍然相同。但这不是很好的

;确保内容仍然相同";以及";执行它";。

2004年,公布了一个不可能的结果,表明没有可移植的、确定性的技术来避免TOCT-TOU竞赛条件

-https://web.cecs.pdx.edu/~markm/CS333/讲义/tocttou.pdf

你可以做几件事来缓解它:

  • 不要使用文件!你说你的内存中有一些代码需要执行:你能在同一个过程中自己执行吗?

  • 缩短时间窗口。

  • 使文件名随机且难以预测其他进程。

  • 在不太可能有攻击者(或恶意程序(运行的地方,以独立用户身份运行程序,并将文件读/写限制为仅限新用户。

最新更新