2

We received a bug report (phrased as a security issue) for a program, which stated that when the program creates files on disk, it does not first verify if a symbolic link exists at the file path to be created. Because of that, an attacker may create a symbolic link, which the program (when ran by another user) may try to overwrite, thus overwriting a file that the attacker may not otherwise have write access to.

To illustrate, here is an example with gcc, which is also "vulnerable" to this problem:

  1. Eve sends Alice a .tar.gz file containing a C program. Inside the archive is evil.c, and a.out, which is a symbolic link to /home/alice/.xinitrc.
  2. Under some pretense, Eve asks Alice to compile the program (and do nothing else).
  3. Eve runs gcc evil.c, which by itself should be safe (barring buffer overflows etc. in the compiler).
  4. gcc (technically the linker) will try to write the resulting binary to a.out, thus overwriting Alice's .xinitrc.
  5. Next time Alice starts her X server, Eve's code runs.

In our case, the situation is very much like gcc - the program creates files only under the current directory (unless told otherwise), with predictable names, and does not by itself execute any code from its input.

Is this something that programs such as compilers need to worry about?

  • Maybe this question is more valid for https://unix.stackexchange.com – GypsyCosmonaut Jul 07 '17 at 22:27
  • 1
    This is not UNIX-specific - Windows supports symbolic links and junctions, which some archiving software will store and recreate upon unpacking. The Windows equivalent of .xinitrc could be the "Startup" folder in the start menu. – Vladimir Panteleev Jul 07 '17 at 22:29
  • 1
    I tested this on Linux. The compiler doesn't overwrite the target of the softlink; it overwrites the softlink itself... i.e., after compiling the link is gone, a new file with the executable exists. At least in my case, this seems a false flag. – Sas3 Jul 08 '17 at 07:39
  • That's interesting... the symlink is overwritten if it points outside the current directory, but not if it points to a file within the same directory. It indicates that gcc/clang have explicit code to check for, resolve, and overwrite symlinks, so it's definitely not a false flag! gcc and clang actually do take proactive measures to avoid this possible vulnerability, which means that we should probably follow suite. Care to convert your comment into an answer? – Vladimir Panteleev Jul 08 '17 at 10:50

2 Answers2

1

Yes programs should pay attention to symlinks if the programs read or write files from/to directories where users with lower privileges can create symlinks. Otherwise it is possible that a user can read from or write to files which should be protected.

But you should avoid a check like if(!issymlink(path)) { writeto(path) } because that would be prone to a race condition. Instead in linux, for example, you can use the O_NOFOLLOW flag to open to fail with an error if the path points to a symbolic link.

40F4
  • 932
  • 6
  • 16
1

That's a general programming issue. In fact, you should wonder whether you want to override all the links to the file when it is multiply linked. The bug report only references symlinks, but an equivalent problem could exists with hardlinks:

  • user A uses the program to generate (and overwrite if it exists) a file in folder F (say /F/app_file)
  • user A has write access to folder G
  • user B has write access to folder F but not to folder G
  • user B links a file from folder G into folder F (ln /G/file /F/app_file)
  • user A executes the program and overwrite the file in folder G

It is not even strictly Unix related, since Windows also supports links and junctions (as you said in comment).

The common way to avoid that problem is to try to unlink the file before writing to it (assuming C language):

remove(filepath);                  // unlink the file if it was previously multiply linked
FILE *fd = fopen(filepath, "w");   // will not overwrite any file other than filepath
Serge Ballesta
  • 25,636
  • 4
  • 42
  • 84
  • The described "common wa"y is prone to race conditions (especially in shared directories like /tmp). And if user G has no write access she also cannot generate symlinks. – eckes Jul 20 '17 at 09:50
  • @eckes: you can create a link to a file that you have no write access in a folder where you have (ex: `ln /etc/password ~/my_password_copy`, or `ln -s` if on different filesystems). You gain no more access but could subvert another user that actually has write access. For the race condition, it does exists, but it is still the best way I know... – Serge Ballesta Jul 20 '17 at 09:58
  • The best way is to avoid shared directories. (And the O_NOFOLLOW flag) – eckes Jul 20 '17 at 20:06