简体   繁体   中英

Using the readlink function to avoid symbolic link race conditions when opening a file path

I'm reading this paper . On the page 11 the paper says:

Unix applications can obtain access to files without encountering symlink races. This is important for normal application programmers who, for example, might want to write an ftp server that securely checks file system accesses against a security policy. The programmer can accomplish this by leveraging the fact that the current working directory of a process is private state and will not change between the time that it performs a check on a file relative to this directory, and the time that the call completes. The programmer can leverage this to perform a race free open by recursively expanding (via readlink) and following a path one component at a time until they have reached a file, or until they have found that the path violates policy.

The paper is describing a technique for avoiding time-of-check to time-of-use issues when checking and opening a file path. In other words, we have a file path that we want to make sure that it doesn't violate some security policy before opening it. But we should avoid time-of-check to time-of-use issues. The paper is describing a method for doing so using the readlink function. I can't understand the technique that it is describing. Can someone elaborate this technique?

I can't understand the technique that it is describing. Can someone elaborate this technique?

Part of the context for this is:

Our approaches work by coercing applications into always accessing the file system using an access pattern that we can easily verify is safe [...], and then simply disallowing all access that does not conform to this access pattern

The text in question is a description of one kind of access pattern that the application being monitored will be allowed to exercise. This particular pattern avoids a symlink race, which occurs when the target of a symbolic link is changed contemporaneously with checking access to a file via a path that passes through that symlink. In such a case, the check might be based on a different symlink target than the actual access, which may allow security policy to be circumvented.

The pattern described is that the program will actually walk the filesystem tree, one directory at a time, to the directory of the targeted file, expanding symbolic links as it goes. In more detail:

  1. if the path is absolute then chdir() to the root directory and convert the path to a relative one

  2. take the first component of the target path (eg foo in foo/bar/baz )

  3. call readlink() on the one-component relative path (eg foo alone), and

    • if readlink succeeds then recurse on the resolved path, starting at (1);
    • if readlink fails other than with EINVAL then the overall procedure fails with that error number;
  4. If this point is reached then we have successfully resolved the current path component to a non-symlink entry in the current working directory (and the cwd may have changed during the process; see next). In that case,

    • if this is the last component in the path then it is the path to open
    • otherwise, chdir() to that path, make the next path component the current one, and loop back to (3)

An application that consistently employed that approach when opening files would be compatible with a security policy featuring simple rules such as that attempts to open() files are denied if the path is absolute, if it contains more than one component, or if that component is a symbolic link.

The point being made in the paper is that the remaining cases and each step in the above procedure are easy for a policy monitor running in user space, such as Janus's, to check correctly, whereas many other accesses are more difficult. The paper is not trying to say that that procedure is inherently more secure than just opening the file directly by whatever path is given.

A symlink race is a security vulnerability where:

  1. Less-privileged program creates a symlink path where one or more of the links redirect to a less-privileged target.
  2. A more privileged program tries to create a file somewhere along that symlink path.

When that happens, the security of the more-privileged program is compromised.

The solution is for the more privileged program to examine each node in the path using readlink() to verify that no node is redirected from the desired true file path before handling any data to or from that file as secure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM