Share via


ReparsePointAware Class

Definition

Collection of File and Directory utility functions that ensure the files and folders being interacted upon have no Windows reparse points on their paths and that the paths in code match the actual paths on disk.

Reparse point injection is a known/common vector of security exploits. See here for more general information about them: https://docs.microsoft.com/en-us/windows/win32/fileio/reparse-points

The goal of this set of functions is to get a Windows file handle, verify that it is in the expected path and then do all file operations with the same handle. It is NOT a safe pattern to verify the file and then perform any additional operations using the file path as an attacker can exploit the race between the check of the file and the file operation based on the file path. This class of attack is known as Time-of-Check/Time-of-Use (TOCTOU). To avoid this, this class will hold the file handle and perform all operations on the handle once it has been deemed to be in the correct location. Since all operations are based on the file handle, we know we're modifying the file that we verified to be correct.

public static class ReparsePointAware
type ReparsePointAware = class
Public Class ReparsePointAware
Inheritance
ReparsePointAware

Methods

CreateDirectory(String)

Creates all directories and subdirectories in the specified path. If the directory's canonical path contains Windows Reparse Points, UnauthorizedAccessException is thrown.

CreateText(String)

Creates or opens a file for writing UTF-8 encoded text. If opening an existing file, the file is truncated. If the file's canonical path contains Windows Reparse Points, UnauthorizedAccessException is thrown and nothing is written.

DeleteFile(String)

Deletes the specified file. If the file's canonical path contains Windows Reparse Points, UnauthorizedAccessException is thrown and nothing is deleted.

GetFinalPath(SafeFileHandle)

Get the full canonical path to a given SafeFileHandle, with every reparse point expanded.

HasReparsePoints(SafeFileHandle, String)

Checks if the file system object represented by the SafeFileHandle has a canonical path that matches the given expectedPath.

MoveFile(String, String)

Moves a specified file to a new location, providing the option to specify a new file name. If the file's canonical path contains Windows Reparse Points, UnauthorizedAccessException is thrown.

OpenFile(String, FileMode, FileAccess, FileShare)

Opens a System.IO.FileStream on the specified path, having the specified mode with read, write, or read/write access and the specified sharing option. If the file's canonical path contains Windows Reparse Points, UnauthorizedAccessException is thrown. OpenFile will pin the directory first before doing any file operations. If pinning the directory fails or the directory is a ReparsePoint, UnauthorizedAccessException will be thrown.

OpenRead(String)

Opens an existing file for reading. If the file's canonical path contains Windows Reparse Points, UnauthorizedAccessException is thrown.

OpenWrite(String)

Opens an existing file or creates a new file for writing. If the file's canonical path contains Windows Reparse Points, UnauthorizedAccessException is thrown.

PinAndRequireNoReparsePoints(String, Boolean)

Opens a SafeFileHandle to an existing file or directory and confirms that the resulting canonical path matches that of the given path. The resulting SafeFileHandle is IDisposable and can be used within using statements to ensure that subsequent file operations are writing to paths without reparse points.

PinHandle(String, Boolean)

Takes a handle on an existing file or directory to ensure that it cannot move.

RequireNoReparsePoints(String, Boolean)

Throws UnauthorizedAccessException if the canonical path is not the same as expectedPath.

RequireSamePath(SafeFileHandle, String)

Throws UnauthorizedAccessException if the given SafeFileHandle's canonical path is not the same as expectedPath.

SetFileAttributeNormal(String)

Checks to see if a file can be deleted by setting FileAttribute = Normal. If unable to set attribute, then user does not have access rights

WriteAllText(String, String)

Creates a new file, writes the specified string to the file, and then closes the file. If the target file already exists, it is overwritten. If the file's canonical path contains Windows Reparse Points, UnauthorizedAccessException is thrown and nothing is written.

Applies to