Red Hat Bugzilla – Bug 492104
CVE-2009-1214 CVE-2009-1215 screen: Unsafe usage of temporary file
Last modified: 2009-04-02 10:55:03 EDT
A security flaw was found in the screen utility in the way it used to create
one particular temporary file. An attacker could use this flaw to perform
a symlink attack.
This issue affects all versions of the screen package, as shipped
with Red Hat Enteprise Linux 2.1, 3, 4, and 5.
This issue affects all versions of the screen package, as shipped
with Fedora releases of 9, 10, and devel.
Proposed patch from Jan Minar:
The Red Hat Security Response Team has rated this issue as having
low security impact, a future update may address this flaw.
More information regarding issue severity can be found here:
Common Vulnerabilities and Exposures assigned an identifier CVE-2009-1214 to
GNU screen 4.0.3 creates the /tmp/screen-exchange temporary file with
world-readable permissions, which might allow local users to obtain
sensitive session information.
Common Vulnerabilities and Exposures assigned an identifier CVE-2009-1215 to
Race condition in GNU screen 4.0.3 allows local users to create or
overwrite arbitrary files via a symlink attack on the
/tmp/screen-exchange temporary file.
I'm not sure why this is noted as a security issue. This is documented behaviour:
Writes the contents of the paste buffer to a public accessible screen-exchange file. This is thought of as a primitive means of communication between screen users on the same host. See also C-a ESC (see section 12.1 Copying).
I read this as a means of data transfer between different screen users which implies that it must be world readable. And since it also indicates that it's a means of communication *between* users (implying back-and-forth), then it must be world writable as well.
Granted, it may not be the most secure thing on the planet, and may not be documented as a security risk, but from what I read above this should be expected behaviour.
The upstream report seems to indicate the same thing.
It might be of concern if screen was suid root, but it isn't; it's sgid screen. The /tmp/screen-exchange file is also created with the ownership of the user who first creates it, so at *best* it could be used to overwrite your own files. And another user cannot remove the file on your behalf and create a symlink because the file is in /tmp which has the sticky bit set, so user A can't remove user B's /tmp/screen-exchange even if it is mode 0666.
Finally, the reporter's proposed patch would be to make the file securely using mode 0600. I would argue that if you do not want this file to be created and used in the documented way, you could set the buffer file to something in your home directory using ~/.screenrc and the bufferfile configuration keyword.
Unless I'm missing something, this shouldn't even be considered a bug.
(In reply to comment #6)
> I read this as a means of data transfer between different screen users which
> implies that it must be world readable. And since it also indicates that it's
> a means of communication *between* users (implying back-and-forth), then it
> must be world writable as well.
Ok, this rules out CVE-2009-1214 as non-issue, as the permissions are intended to be that way. Though CVE-2009-1215 may still be a (fairly minor) issue, if the exchange file is not created correctly.
> The /tmp/screen-exchange file is also created with the ownership of the user
> who first creates it, so at *best* it could be used to overwrite your own
> files. And another user cannot remove the file on your behalf and create a
> symlink because the file is in /tmp which has the sticky bit set
The case you are forgetting is user B creates symlink pointing to some user A's file, that should be corrupted. Then B convinces A to use this exchange feature. If pre-created symlink can trick screen to destroy A's file, it can be a problem. However, screen does not seem to allow that.
Briefly explained in upstream bugreport:
few more details here. Relevant code if is in WriteFile() / fileio.c.
417 exists = !lstat(fn, &stb);
418 if (public && exists && (S_ISLNK(stb.st_mode) || stb.st_nlink > 1))
420 Msg(0, "No write to links, please.");
Exchange file is lstat-ed first. If it is symlink, or non-symlink with multiple hardlinks, screen gives an error and nothing gets written to exchange file.
If file does not exist at the time of lstat (or lstat fails for some other reason), the code path used leads to open with O_CREAT | O_EXCL, not allowing link attack:
402 if (exists)
[ ... ]
451 fd = open(fn, O_WRONLY|O_CREAT|O_EXCL, 0666);
452 f = fd >= 0 ? fdopen(fd, mode) : 0;
So the only case that remains is that lstat succeeds and an attacker tries to race against screen in between lstat and open. At lstat time, attacker-controlled exchange file must exist and must not be link. Regular file would do. Open is done with O_WRONLY and returned file descriptor is fstat-ed and checked against previous lstat output. Device numbers and inodes are compared.
404 if ((fd = open(fn, O_WRONLY, 0666)) >= 0)
406 if (fstat(fd, &stb2) == 0 && stb.st_dev == stb2.st_dev && stb.st_ino == stb2.st_ino)
407 ftruncate(fd, 0);
411 fd = -1;
During that race, attacker needs to replace regular file with hard or symbolic link.
For hard link, the device / inode number check will fail for any file that existed before A used this copy to exchange file feature. (In theory, A's file created after B unlinks his exchange file but before A's screen calls open can be targeted, but this is actually a double race with B not really being able to control whether some other file is created by A at the right time.)
Symlink case is similar. fstat does not stat B's symlink, but rather an A's target file. Device / inode check should only succeed for A's file created somewhere in between the mentioned double race.
As noted above, this feature it not the most secure thing on the planet, but I wouldn't expect it to be used very often (I'm screen user myself and I've never heard of it before ;). It's probably not much that can be done to improve this (possibly pre-create the exchange file as root and make it world or screen group writable, this would likely require it's move from /tmp to /var), but it's not really worth treating as security flaw that may require backporting fixes to already released versions of screen.
Launchpad bug also refers to other Debian bug that reportedly changes this code in some way, so this may not apply to Debian/Ubuntu version of screen. This analysis should apply to all screen versions in Red Hat Enterprise Linux 2.1, 3, 4 and 5, and current Fedora versions (9, 10), where we do not seem to divert from upstream in any way.
Ah, I see the Debian change now, it comments out following line:
public = !strcmp(fn, DEFAULT_BUFFERFILE);
Due to that, /tmp/screen-exchange is treated as "private", i.e. it does not have 666 permissions set, but also all anti-symlink attack tests are skipped as well. Similar can be re-created by setting bufferfile option to something in /tmp, but not the default name.