protonscr

Symlink attack in /usr/bin/steam wrapper

steamopen reviewedruntime
ValveSoftware/steam-for-linux#2716 · opened 2013-07-21 by antarus12345 · updated 2025-01-19 · 1 comments · github
Aantarus12345 2013-07-21 github

/usr/bin/steam is a shell wrapper that sets up an environment to run the steam client. It has a segment of code that poorly handles paths in /tmp, making it vulnerable to a symlink attack from other (possibly unprivileged) local users.

cd "$LAUNCHSTEAMDIR"
if [ "command -v tee" != "" ]; then
mkdir -p --mode=777 /tmp/dumps
exec "$LAUNCHSTEAMDIR/$STEAMBOOTSTRAP" "$@" 2>&1 | tee "/tmp/dumps/${USER}_stdout.txt"
else
exec "$LAUNCHSTEAMDIR/$STEAMBOOTSTRAP" "$@"
fi

This attempts to log the steam client's stdout to /tmp/dumps/${USER}_stdout.txt. However it has a number of errors in it:

  1. Usually when writing to /tmp, you should use mktemp (or mkdtemp). In fact, the script does this on line 38, in function show_message. Because /tmp/dumps is easily guessable, an attacker can symlink /tmp/dumps to some other directory and cause steam to write its files there.

  2. You also tee the output to an easily guessable filename, inside of an easily guessable directory, which is world-writable (and not marked sticky...for some reason..) If there are 2 users on a given system, one could symlink /tmp/dumps/victim_stdout.txt to a file in /home/victim, such as their bitcoin wallet, ssh keys, steam configuration, etc... and cause it to get overwritten by steam.

Some advice to consider:

  1. Not bothering with /tmp at all. Write the logs to $HOME somewhere. Rotate them, and just keep the last few logfiles. See for example $HOME/.xsession for an example.
  2. Per-user directories in /tmp. Much easier to secure.
  3. If you are going to make a directory 777, at least make it 1777. The sticky bit is important to prevent users from deleting each others files. I realize this is unlikely a practical problem for steam; but it is trivial to fix.
  4. You cannot write files to easily guessable filenames in a world-writable directory (/tmp/dumps is just as bad as /tmp in this regard.) This is solvable by picking a better filename argument for tee, similar to line 38
    tee_file=$(mktemp --tmpdir=/tmp/dumps XXXXXX_${USER}_stdout.txt || echo "/tmp/dumps/${USER}_stdout.txt")
    exec "$LAUNCHSTEAMDIR/$STEAMBOOTSTRAP" "$@" 2>&1 | tee "${tee_file"

for example.

AAthanasius 2025-01-19 github

And, this being the Linux client, it could actually make use of TMPDIR if it's set.

I had a steam client crash yesterday which caused a dump to be written. I had TMPDIR set to an alternate (and only accessible by my user) location, but this was ignored in favour of just writing in /tmp/dumps.

That caused my root partition to fill up, which I only noticed when a game failed to launch today. Took me a while to spot the issue, given I was looking all over / for where I could free up space.

That /tmp shouldn't be hard-coded, just a fallback if TMPDIR is not set.

Nothing extracted yet.