org.sonar.plugins.csharp.S5445.html Maven / Gradle / Ivy
Temporary files are considered insecurely created when the file existence check is performed separately from the actual file creation. Such a
situation can occur when creating temporary files using normal file handling functions or when using dedicated temporary file handling functions that
are not atomic.
Why is this an issue?
Creating temporary files in a non-atomic way introduces race condition issues in the application’s behavior. Indeed, a third party can create a
given file between when the application chooses its name and when it creates it.
In such a situation, the application might use a temporary file that it does not entirely control. In particular, this file’s permissions might be
different than expected. This can lead to trust boundary issues.
What is the potential impact?
Attackers with control over a temporary file used by a vulnerable application will be able to modify it in a way that will affect the application’s
logic. By changing this file’s Access Control List or other operating system-level properties, they could prevent the file from being deleted or
emptied. They may also alter the file’s content before or while the application uses it.
Depending on why and how the affected temporary files are used, the exploitation of a race condition in an application can have various
consequences. They can range from sensitive information disclosure to more serious application or hosting infrastructure compromise.
Information disclosure
Because attackers can control the permissions set on temporary files and prevent their removal, they can read what the application stores in them.
This might be especially critical if this information is sensitive.
For example, an application might use temporary files to store users' session-related information. In such a case, attackers controlling those
files can access session-stored information. This might allow them to take over authenticated users' identities and entitlements.
Attack surface extension
An application might use temporary files to store technical data for further reuse or as a communication channel between multiple components. In
that case, it might consider those files part of the trust boundaries and use their content without additional security validation or sanitation. In
such a case, an attacker controlling the file content might use it as an attack vector for further compromise.
For example, an application might store serialized data in temporary files for later use. In such a case, attackers controlling those files'
content can change it in a way that will lead to an insecure deserialization exploitation. It might allow them to execute arbitrary code on the
application hosting server and take it over.
How to fix it
Code examples
The following code example is vulnerable to a race condition attack because it creates a temporary file using an unsafe API function.
Noncompliant code example
using System.IO;
public void Example()
{
var tempPath = Path.GetTempFileName(); // Noncompliant
using (var writer = new StreamWriter(tempPath))
{
writer.WriteLine("content");
}
}
Compliant solution
using System.IO;
public void Example()
{
var randomPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
using (var fileStream = new FileStream(randomPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, 4096, FileOptions.DeleteOnClose))
using (var writer = new StreamWriter(fileStream))
{
writer.WriteLine("content");
}
}
How does this work?
Applications should create temporary files so that no third party can read or modify their content. It requires that the files' name, location, and
permissions are carefully chosen and set. This can be achieved in multiple ways depending on the applications' technology stacks.
Strong security controls
Temporary files can be created using unsafe functions and API as long as strong security controls are applied. Non-temporary file-handling
functions and APIs can also be used for that purpose.
In general, applications should ensure that attackers can not create a file before them. This turns into the following requirements when creating
the files:
- Files should be created in a non-public directory.
- File names should be unique.
- File names should be unpredictable. They should be generated using a cryptographically secure random generator.
- File creation should fail if a target file already exists.
Moreover, when possible, it is recommended that applications destroy temporary files after they have finished using them.
Here the example compliant code uses the Path.GetTempPath
and Path.GetRandomFileName
functions to generate a unique
random file name. The file is then open with the FileMode.CreateNew
option that will ensure the creation fails if the file already
exists. The FileShare.None
option will additionally prevent the file from being opened again by any process. To finish, this code ensures
the file will get destroyed once the application has finished using it with the FileOptions.DeleteOnClose
option.
Resources
Documentation
- OWASP - Insecure Temporary File
Standards