Reputation: 2858
Let's say I have contents of an executable (or a bat script, doesn't matter) in memory and want to run it as a new process. That is easy.
File.WriteAllBytes(filePath, contents);
// gap
Process.Start(filePath)
But I want to make sure that the executed file is not tampered by any other process. And there is a gap between file creation and execution. It gives a chance to tamper the file with the right tools.
So, instead of File.WriteAllBytes
, I went with opening a FileStream FileShare.Read
and keeping it open until the execution has finished.
using(var fileStream = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
{
Process.Start(filePath)
}
But this doesn't work. Process.Start
fails with:
System.ComponentModel.Win32Exception (32): The process cannot access the file because it is being used by another process.
This question and its answer explains why I think. In a nutshell, Process.Start
will attempt to open the file with FileShare.Read
and fail because the open FileStream already has Write Access, hence failing the FileShare.Read
attempt of the process.
Is there a way to do this cleanly?
A workaround I can think of is to save the file, close it, open a new FileStream with FileShare.Read
and FileAccess.Read
, make sure the content is still the same before executing it. But that's not pretty.
Upvotes: 0
Views: 302
Reputation: 15203
What you are describing is a classic case of Time of check to time of use vulnerability.
Any solution that involves checking something and then executing it, and where those two operations are not atomic, will still leave you vulnerable. For example:
make sure the content is still the same before executing it. But that's not pretty
There's still a (smaller) gap (timing window) between the "make sure the content is still the same" and "executing it".
In 2004, an impossibility result was published,showing that there was no portable, deterministic technique for avoiding TOCT-TOU race conditions
- https://web.cecs.pdx.edu/~markem/CS333/handouts/tocttou.pdf
You can do a couple of things to mitigate it:
Don't use files! You say you have some code in memory that you need to execute: can you execute it yourself in the same process?
Reduce the window of time.
Make the file name random and hard to predict for other processes.
Run your program as a separate user where there's less likelyhood an attacker (or malicious program) is running, and restrict the file read/write to the new user only.
Upvotes: 1