[3333] in bugtraq
[linux-security] samba 1.9.16p2-2 (RedHat): Damn /tmp security
daemon@ATHENA.MIT.EDU (Zygo Blaxell)
Tue Sep 10 14:58:00 1996
Date: Tue, 10 Sep 1996 12:38:20 -0500
Reply-To: Zygo Blaxell <zblaxell@MYRUS.COM>
From: Zygo Blaxell <zblaxell@MYRUS.COM>
To: Multiple recipients of list BUGTRAQ <BUGTRAQ@netspace.org>
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