MTimeProtectedFileStorage
class MTimeProtectedFileStorage extends MTimeProtectedFastFileStorage (View source)
Stores PHP code in files with securely hashed names.
The goal of this class is to ensure that if a PHP file is replaced with an untrusted one, it does not get loaded. Since mtime granularity is 1 second, we cannot prevent an attack that happens within one second of the initial save(). However, it is very unlikely for an attacker exploiting an upload or file write vulnerability to also know when a legitimate file is being saved, discover its hash, undo its file permissions, and override the file with an upload all within a single second. Being able to accomplish that would indicate a site very likely vulnerable to many other attack vectors.
Each file is stored in its own unique containing directory. The hash is based on the virtual file name, the containing directory's mtime, and a cryptographically hard to guess secret string. Thus, even if the hashed file name is discovered and replaced by an untrusted file (e.g., via a move_uploaded_file() invocation by a script that performs insufficient validation), the directory's mtime gets updated in the process, invalidating the hash and preventing the untrusted file from getting loaded. Also, the file mtime will be checked providing security against overwriting in-place, at the cost of an additional system call for every load() and exists().
The containing directory is created with the same name as the virtual file name (slashes replaced with hashmarks) to assist with debugging, since the file itself is stored with a name that's meaningless to humans.
Properties
| protected string | $directory | The directory where the files should be stored. |
from FileStorage |
| protected string | $secret | The secret used in the HMAC. |
from MTimeProtectedFastFileStorage |
Methods
Constructs this MTimeProtectedFastFileStorage object.
Checks whether the PHP code exists in storage.
Loads PHP code from storage.
Ensures the directory exists, has the right permissions, and a .htaccess.
Ensures the requested directory exists and has the right permissions.
Gets the full path where the file is or should be stored.
Gets the full path of the containing directory where the file is or should be stored.
Clears PHP's stat cache and returns the directory's mtime.
A brute force tempnam implementation supporting streams.
Determines whether a protected file exists and sets the filename too.
{@inheritdoc}
Details
__construct(array $configuration)
Constructs this MTimeProtectedFastFileStorage object.
bool
exists(string $name)
Checks whether the PHP code exists in storage.
load(string $name)
Loads PHP code from storage.
Depending on storage implementation, exists() checks can be expensive, so this function may be called for a file that doesn't exist, and that should not result in errors. This function does not return anything, so it is up to the caller to determine if any code was loaded (for example, check class_exists() or function_exists() for what was expected in the code).
bool
save(string $name, $data)
Saves PHP code to storage.
protected
ensureDirectory(string $directory, int $mode = 0777)
Ensures the directory exists, has the right permissions, and a .htaccess.
For compatibility with open_basedir, the requested directory is created using a recursion logic that is based on the relative directory path/tree: It works from the end of the path recursively back towards the root directory, until an existing parent directory is found. From there, the subdirectories are created.
protected bool
createDirectory(string $directory, int $mode = 0777)
Ensures the requested directory exists and has the right permissions.
For compatibility with open_basedir, the requested directory is created using a recursion logic that is based on the relative directory path/tree: It works from the end of the path recursively back towards the root directory, until an existing parent directory is found. From there, the subdirectories are created.
bool
delete(string $name)
Deletes PHP code from storage.
string|false
getFullPath(string $name, string $directory = NULL, int $directory_mtime = NULL)
Gets the full path where the file is or should be stored.
This function creates a file path that includes a unique containing directory for the file and a file name that is a hash of the virtual file name, a cryptographic secret, and the containing directory mtime. If the file is overridden by an insecure upload script, the directory mtime gets modified, invalidating the file, thus protecting against untrusted code getting executed.
bool
writeable()
Whether this is a writable storage.
deleteAll()
Removes all files in this bin.
protected bool
unlink(string $path)
Deletes files and/or directories in the specified path.
If the specified path is a directory the method will call itself recursively to process the contents. Once the contents have been removed the directory will also be removed.
array
listAll()
Lists all the files in the storage.
garbageCollection()
Performs garbage collection on the storage.
The storage may choose to delete expired or invalidated items.
protected string
getContainingDirectoryFullPath(string $name)
Gets the full path of the containing directory where the file is or should be stored.
protected
getUncachedMTime($directory)
Clears PHP's stat cache and returns the directory's mtime.
protected string
tempnam($directory, $prefix)
A brute force tempnam implementation supporting streams.
protected string|false
checkFile(string $name)
Determines whether a protected file exists and sets the filename too.
getPath($name)
{@inheritdoc}