Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I protect against hard link attacks?

Tags:

c

linux

security

  • I want to append data to a file in /tmp.
  • If the file doesn't exist I want to create it
  • I don't care if someone else owns the file. The data is not secret.
  • I do not want someone to be able to race-condition this into writing somewhere else, or to another file.

What is the best way to do this?

Here's my thought:

fd = open("/tmp/some-benchmark-data.txt", O_APPEND | O_CREAT | O_NOFOLLOW | O_WRONLY, 0644);
fstat(fd, &st);
if (st.st_nlink != 1) {
    HARD LINK ATTACK!
}

Problem with this: Someone can link the file to some short-lived file of mine, so that /tmp/some-benchmark-data.txt is the same as /tmp/tmpfileXXXXXX which another script of mine is using (and opened properly using O_EXCL and all that). My benchmark data is then appended to this /tmp/tmpfileXXXXXX file, while it's still being used.

If my other script happened to open its tempfile, then delete it, then use it; then the contents of that file would be corrupted by my benchmark data. This other script would then have to delete its file between the open() and the fstat() of the above code.

So in other words:

This script          Dr.Evil        My other script or program
                                    open(fn2, O_EXCL | O_CREAT | O_RDWR)
                     link(fn1,fn2)
open(fn1, ...)
                                     unlink(fn2)
fstat(..)=>link is 1
write(...)
close(...)
                                    write(...)
                                    seek(0, ...)
                                    read(...) => (maybe) WRONG DATA!

And therefore the above solution does not work. There are quite possibly other attacks.

What's the right way? Besides not using a world-writable directory.

Edit: In order to protect against the result that the evil user creates the file with his/her ownership and permissions, or just wrong permissions (by hard linking your file and then removing the original, or hardlinking a short-lived file of yours) I can check the ownership and permission bits after the nlink check.

There would be no security issue, but would also prevent surprises. Worst case is that I get some of my own data (from another file) at the beginning of the file copied from some other file of mine.

Edit 2: I think it's almost impossible to protect against someone hard-linking the name to a file that's opened, deleted and then used. Examples of this is EXE packers, which sometimes even execute the deleted file via /proc/pid/fd-num. Racing with this would cause the execution of the packed program to fail. lsof could probably find if someone else has the inode opened, but it seems to be more trouble than it's worth.

like image 625
Thomas Avatar asked Mar 31 '10 06:03

Thomas


2 Answers

Whatever you do, you'll generally get a race condition where someone else creates a link, then removes it by the time your fstat() system call executes.

You've not said exactly what you're trying to prevent. There are certainly kernel patches which prevent making (hard or symbolic) links to files you don't own in world-writable directories (or sticky directories).

Putting it in a non world-writable directory seems to be the right thing to do.

SELinux, which seems to be the standard enhanced security linux, may be able to configure policy to forbid users to do bad things which break your app.

In general, if you're running as root, don't create files in /tmp. Another possibility is to use setfsuid() to set your filesystem uid to someone else, then if the file isn't writable by that user, the operation will simply fail.

like image 112
MarkR Avatar answered Sep 22 '22 15:09

MarkR


Short of what you just illustrated, the only other thing I've tried ended up almost equally racey and more expensive, establishing inotify watches on /tmp prior to creating the file, which allows for catching the event of a hardlink in some instances.

However, its still really racey and inefficient, as you would also need to complete a breadth first search of /tmp, at least up to the level that you want to create the file.

There (to my knowledge) is no "sure" way to avoid this kind of race, other than not using word writeable directories. What are the consequences of someone intercepting your i/o via hard link .. would they get anything useful or just make your application exhibit undefined behavior?

like image 20
Tim Post Avatar answered Sep 25 '22 15:09

Tim Post