Package: galeon
Version: 2.0.6-2.1
Severity: grave
Tags: security patch
Justification: user security hole

When opening an URL with a helper app, the file is created with the
user's umask (so usually world-readable), and often survives closing
the helper app and galeon. This leaks which documents have been read
from the web by the user to all users of the machine. The document is
also downloaded under its original filename, which is also a partial
information leak.

 Very precisely, the file is downloaded securely (made-up name and
 mode 0600), but then renamed to the name it had in the URL and
 chmod'ed to the user's umask, minus the x bits.

As a side-effect, the download fails (the download progress UI just
freezes) if the filename already exists and is not deletable /
writable by the user. (If it exists and is writable, it will silently
overwrite it.)

The attached patch mostly fixes the security problem by changing the
temporary directory to a mode 0700 subdirectory. It still leaves the
filename in the command line of the helper app. It also does not clean
up the created temporary directory.

The root cause is this in this code in GProgressListener::Init in line
208 of mozilla/ProgressListener.cpp:

                        /* HACK, stop mozilla from opening the application, we
                         * do it ourselves */
                        aMIMEInfo->SetPreferredAction(nsIMIMEInfo::saveToDisk);

This causes xulrunner to not only opening the application, but also
forcibly renaming the file to its "suggested name" (because it assumes
that it comes from the "Save File" dialog, where the user was asked to
confirm any overwrite) and chmod'ing to the user's umask (calling
"FixPermissions" line 1804 of
uriloader/exthandler/nsExternalHelperAppService.cpp, in function
nsExternalAppHandler::ExecuteDesiredAction).

Hmmm... I wonder if this does not in itself introduce a rather long
race condition between the download (in a temporary name) and the
rename, when the download is made in a directory that is writable by
other users, and where that other user can arrange for the file not to
be deletable by the user (directory owned by that other user?) (I'm
thinkging of a symlink attack, that kind of thing). Opinions?

-- System Information:
Debian Release: 5.0
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.26-1-amd64 (SMP w/2 CPU cores)
Locale: LANG=fr_LU.UTF-8, LC_CTYPE=fr_LU.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages galeon depends on:
ii  galeon-common              2.0.6-2.1     GNOME web browser for advanced use
ii  gconf2                     2.22.0-1      GNOME configuration database syste
ii  libbonobo2-0               2.22.0-1      Bonobo CORBA interfaces library
ii  libbonoboui2-0             2.22.0-1      The Bonobo UI library
ii  libc6                      2.7-18        GNU C Library: Shared libraries
ii  libgcc1                    1:4.3.3-3     GCC support library
ii  libgconf2-4                2.22.0-1      GNOME configuration database syste
ii  libglade2-0                1:2.6.3-1     library to load .glade files at ru
ii  libglib2.0-0               2.16.6-1      The GLib library of C routines
ii  libgnome-desktop-2         2.22.3-2      Utility library for loading .deskt
ii  libgnome2-0                2.20.1.1-2    The GNOME 2 library - runtime file
ii  libgnomeui-0               2.20.1.1-2    The GNOME 2 libraries (User Interf
ii  libgnomevfs2-0             1:2.22.0-5    GNOME Virtual File System (runtime
ii  libgtk2.0-0                2.12.11-4     The GTK+ graphical user interface 
ii  libnspr4-0d                4.7.1-4       NetScape Portable Runtime Library
ii  liborbit2                  1:2.14.16-0.1 libraries for ORBit2 - a CORBA ORB
ii  libpango1.0-0              1.20.5-3      Layout and rendering of internatio
ii  libpopt0                   1.14-4        lib for parsing cmdline parameters
ii  libstdc++6                 4.3.3-3       The GNU Standard C++ Library v3
ii  libx11-6                   2:1.1.5-2     X11 client-side library
ii  libxml2                    2.6.32.dfsg-5 GNOME XML library
ii  procps                     1:3.2.7-11    /proc file system utilities
ii  xulrunner-1.9              1.9.0.6-1     XUL + XPCOM application runner

Versions of packages galeon recommends:
ii  gnome-control-center        1:2.22.2.1-2 utilities to configure the GNOME d
ii  gnome-icon-theme            2.22.0-1     GNOME Desktop icon theme
ii  iso-codes                   3.6-1        ISO language, territory, currency,
ii  scrollkeeper                0.3.14-16    A free electronic cataloging syste
ii  yelp                        2.22.1-8+b1  Help browser for GNOME 2

Versions of packages galeon suggests:
pn  mozplugger                    <none>     (no description available)

-- no debconf information
diff -u galeon-2.0.6/debian/changelog galeon-2.0.6/debian/changelog
--- galeon-2.0.6/debian/changelog
+++ galeon-2.0.6/debian/changelog
@@ -1,3 +1,10 @@
+galeon (2.0.6-2.1) unstable; urgency=high
+
+  * Use dedicated temporary directory; avoids world-readable
+    temporary files (Closes: #TODO)
+
+ -- Lionel Elie Mamane <lmam...@debian.org>  Sat, 07 Feb 2009 14:35:20 +0100
+
 galeon (2.0.6-2) unstable; urgency=low
 
   * New patch, 50_configure-tests-flags, use proper CFLAGS/LDFLAGS/CPPFLAGS
--- galeon-2.0.6.orig/src/galeon-main.c
+++ galeon-2.0.6/src/galeon-main.c
@@ -40,6 +40,8 @@
 #include <gtk/gtkwindow.h>
 #include <gdk/gdkx.h>
 #include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #ifdef ENABLE_NLS
 # include <locale.h>
 #endif
@@ -259,6 +261,38 @@
 	}
 	else
 	{
+
+		{
+			char *ntmpdir, *p;
+			unsigned int i = 0;
+			size_t ol, nl;
+			int r;
+			char *otmpdir = getenv("TMPDIR");
+			const char *pattern = "galeon-tmp-";
+			const size_t pl = strlen(pattern);
+			const size_t max_ilen = sizeof(i)*2;
+			if ( otmpdir == NULL || *otmpdir == '\0' )
+				otmpdir = getenv("TMP");
+			if ( otmpdir == NULL || *otmpdir == '\0' )
+				otmpdir = getenv("TEMP");
+			if ( otmpdir == NULL || *otmpdir == '\0' )
+				otmpdir = "/tmp/";
+			ol = strlen(otmpdir);
+			nl = pl + max_ilen + 1 + ol;
+			ntmpdir = malloc(nl);
+			if ( ntmpdir == NULL)
+				abort();
+			strncpy(ntmpdir, otmpdir, nl);
+			p = ntmpdir + ol;
+			strcpy(p, pattern);
+			p += pl;
+			while ( (r=mkdir(ntmpdir, S_IRUSR | S_IWUSR | S_IXUSR)) != 0 &&
+				errno == EEXIST && i < UINT_MAX )
+				snprintf(p, max_ilen, "%x", i++);
+			if ( r != 0 || setenv("TMPDIR", ntmpdir, -1) != 0 )
+				abort();
+		}
+
 		galeon_debug_init ();
 
 		gul_state_init ();

Reply via email to