1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
## 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 real 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) direcgtory 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.
## What about symlinks?
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.
## 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.
|