aboutsummaryrefslogtreecommitdiffstats

What is safepath?

safepath is tiny library written in C, targeting POSIX systems.

Its core functionality is concentrated in a single function safepath_check.

safepath_check performs one function: it takes a filename consisting of one or more path components, and returns an indication whether that name is safe for the process to use.

Safe means that the pathname doesn't contain any component which could be tampered with by a user other than the effective user ID of the caller, or else root.

What is significance of this check?

Checking the permissions of an object is insufficient. Suppose we are a superuser process such as a server trying to access some application- specific password file /data/path/to/passwd.

If we check that the permissions and ownership on this passwd file are all right (root owns it, and it's not writable to anyone), that is not by itself secure. If any of the directories in the path are open, an attacker could, for instance, insert a symbolic link like /data/path/to -> /malicious/to where /malicious/to/passwd is another link to /etc/passwd.

How does safepath_check defend against this sort of thing?

safepath_check processes the path from left to right, very carefully. Component by component it checks that every element is not writable to anyone but the calling user (identified by getuid) or else root (which is implicitly trusted).

safepath_check begins by validating the / (root) directory if the input is an absolute path, or else the current directory . (dot) if the path is relative. It then goes from there.

If safepath_check encounters an insecure directory, it stops and reports it.

If safepath_check encounters a symlink, it performs its own symlink resolution, carefully. It reads the symlink target, grafts it in place of the symlink, and then starts checking the substituted path in the same way.

safepatch_check stops after 8 levels of symlink indirection, reporting a loop. This is stricter than most systems' threshold for reporting ELOOP in name lookup.

safepath_check does not rely on the operating system symlink resolution, which will transparently resolve multiple levels of symlink indirection. This is not safe: symlinks can point to other symlinks. A symlink which has tamper-proof permissions can point to a symlink which has weak permission and can be manipulated by a different user. Every level of symlink resolution must be performed by substitution, and a check of all the new components that are thus inserted into the path.

Known caveats

safepath_check accepts both relative and absolute paths. Checking a relative path begins with the "." directory, whereupon it is implicitly trusted that the process had safely changed to this directory somehow. However, that may not be so. The process may have traversed an untrusted directory or symlink when it performed the chdir call to change to the current directory. One might think that calling getcwd and validating the resulting absolute path with safepath_check is enough, but that may not be so: a malicious link could misdirect into a directory which has a safe absolute path. The user's application could thereby be fooled into accessing or modifying data, which the user owns, but which is not the intended target of the access. If relative paths are used, it's recommended to first change to desired directory using an absolute path which is checked for safety.

License

safepath is offered under the two-clause BSD license. See the copyright header in the source files and the LICENSE file in the source tree.