Bugtraq mailing list archives

[linux-security] samba 1.9.16p2-2 (RedHat): Damn /tmp security


From: zblaxell () myrus com (Zygo Blaxell)
Date: Tue, 10 Sep 1996 12:38:20 -0500


While I was RTFM(smb.conf) just now:

  lpq cache time (G)
      This controls how long lpq info will be cached for to pre-
      vent  the  lpq  command being called too often. A separate
      cache is kept for each variation of the lpq  command  used
      by  the  system,  so if you use different lpq commands for
      different users then they won't share cache information.

smb.conf                     smb.conf                          24

SMB.CONF(5)                                           SMB.CONF(5)

      The cache files are stored in /tmp/lpq.xxxx where xxxx  is
      a hash of the lpq command in use.

Doh!  "Don't worry," I said to myself.  "They implemented this correctly.
There should be no symlink-based race conditions.  Better check anyway..."

From source/util.c, where this file gets opened:

/*******************************************************************
lock a file - returning a open file descriptor or -1 on failure
The timeout is in seconds. 0 means no timeout
********************************************************************/
int file_lock(char *name,int timeout)
{
 int fd = open(name,O_RDWR|O_CREAT,0666);
[ Rest of function deleted...without O_EXCL, it's already too late ]
}

Doh!  Oh well, there goes my coffee break for the afternoon.

Is there a good document that explains how to use O_EXCL and/or mkstemp()
out there somewhere?  If not, it's about time I write one.

To make matters worse, this is one of the few paths that is hard-coded
into smbd.  No getenv(TMPDIR), no configuration option...just
'sprintf(outfile,"/tmp/lpq.%08x",str_checksum(syscmd));'.

Also, disabling lpq caching doesn't disable creation of this file; it
deletes the cache file after writing it.

Defining the lpq command to be null will fix the security problem,
but disables all access to the printer queue in the process.

Fixing this bug will involve rewriting source/printing.c:get_printqueue(),
as that function depends on first collecting lpq output in a file then
reading that file back into memory.

I have not checked for the presence of other bugs of this type.  They may
exist.

Possible alternative solutions follow.  I like #1, because it's the
easiest to implement and verify.

1.  Parameterize that path, e.g. 'lpqcachedir = /var/lib/samba/lpq-cache'
    in smb.conf, document it, and disable the lpq cache (including
    any file creation) unless a path is given.  Problem:  'lpqcachedir =
    /tmp' makes the bug come back; also, it is necessary to clean the
    lpq cache separately.

2.  Create the cache files securely (with O_EXCL), and use them only
    if they are mode 666 and have exactly one link; otherwise, ignore
    them.  Only read the cache files if the filename is not a symlink,
    and the link count of the open file descriptor is 1, and the device
    and inode numbers of the open file descriptor are equal to the values
    returned from lstat on the filename.  Problem: this permits denial of
    service.

3.  Guarantee that an unprivileged user is creating this file.  Problem:
    this isn't really a solution, and denial-of-service is still possible:
    if /tmp/lpq.xxxxxxxx is linked to /dev/zero, the smbd process will
    consume infinite memory while reading the file back.

In addition, the following would be nice to have to close out any
further attacks: Rewrite get_printqueue() to not require a temporary file.
Since the output of lpq is stored in memory anyway, this can't be too
hard.  If (and only if) the cache file can be created and used securely
as in #2, the results could be cached by one large fwrite() from memory.
--
Zygo Blaxell. Unix/soft/hardware guru, was for U of Waterloo CS Club, now for
(name withheld by request). 10th place, ACM Intl Collegiate Programming Contest
Finals, 1994.  Admin Linux/TCP/IP for food, clothing, anime.  Pager: 1 (613)
760 8572.  "I gave up $1000 to avoid working on windoze... *sigh*" - Amy Fong



Current thread: