[Fusionforge-commits] r8451 - in trunk/gforge: deb-specific debian plugins/scmcvs/cronjobs

Roland Mas lolando at libremir.placard.fr.eu.org
Mon Nov 30 17:33:34 CET 2009


Author: lolando
Date: 2009-11-30 17:33:34 +0100 (Mon, 30 Nov 2009)
New Revision: 8451

Modified:
   trunk/gforge/deb-specific/ssh_dump_update.pl
   trunk/gforge/debian/changelog
   trunk/gforge/plugins/scmcvs/cronjobs/ssh_create.php
Log:
Fix for symlink attack discovered by Sylvain Beucler (CVE-2009-3304).

Modified: trunk/gforge/deb-specific/ssh_dump_update.pl
===================================================================
--- trunk/gforge/deb-specific/ssh_dump_update.pl	2009-11-30 16:31:45 UTC (rev 8450)
+++ trunk/gforge/deb-specific/ssh_dump_update.pl	2009-11-30 16:33:34 UTC (rev 8451)
@@ -2,8 +2,65 @@
 #
 # ssh_dump.pl - Script to suck data outta the database to be processed by ssh_create.pl
 #
+# Symlink attack fix Copyright (C) 2009 Sylvain Beucler / GPLv2+ / no warranty
 use DBI;
+use English;
 
+## Become this effective user (EUID/EGID) and perform this action.
+## 
+## This protect against symlink attacks; they are inevitable when
+## working in a directory owned by a local user.  We could naively
+## check for the presence of symlinks, but then we'd still be
+## vulnerable to a symlink race attack.
+## 
+## We'll use set_e_uid/set_e_gid for efficiency and simplicity
+## (e.g. we can get the return value directly), which is enough for
+## opening files and similar basic operations.  When calling external
+## programs, you should use fork&exec&setuid/setgid.
+## 
+# arg1: username
+# arg2: a Perl sub{}
+sub SudoEffectiveUser {
+    my $user = $_[0];
+    my $sub_unprivileged = $_[1];
+
+    my ($uid,$gid) = GetUserUidGid($user);
+    if ($uid eq "" or $gid eq "") {
+	print "Unknown user: $user";
+	return;
+    }
+
+    my $old_GID = $GID; # save additional groups
+    $! = '';
+    $EGID = "$gid $gid"; # set egid and additional groups
+    if ($! ne '') {
+	warn "Cannot setegid($gid $gid): $!";
+	return;
+    }
+    $EUID = $uid;
+    if ($! ne '') {
+	warn "Cannot seteuid($uid): $!";
+	return;
+    }
+
+    # Perform the action under this effective user:
+    my $ret = &$sub_unprivileged();
+
+    # Back to root
+    undef($EUID);     # restore euid==uid
+    $EGID = $old_GID; # restore egid==gid + additional groups
+
+    return $ret;
+}
+
+## Get system uid/gid
+sub GetUserUidGid {
+    my $user = $_[0];
+    my ($name,$passwd,$uid,$gid,
+	$quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($user);
+    return ($uid,$gid);
+}
+
 # Run as gforge
 my($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = getpwnam("gforge");
 $> = $uid;
@@ -54,10 +111,12 @@
 	
 		if($verbose){print("Writing authorized_keys for $username: ")};
 	
-		if (write_array_file("$ssh_dir/authorized_keys", @user_authorized_keys)) {
+		SudoEffectiveUser($username, sub {
+		    if (write_array_file("$ssh_dir/authorized_keys", @user_authorized_keys)) {
                         warn "Problem writing authorized_keys for $username\n";
                         next;
-                }
+		    }
+				  });
 
 		chown $uid, $uid, ("$homedir_prefix/$username", $ssh_dir, "$ssh_dir/authorized_keys");
 		chmod 0644, "$ssh_dir/authorized_keys";
@@ -95,8 +154,12 @@
 
 	if (-d $ssh_dir) {
 	    if($verbose){print("Resetting authorized_keys for $username: ")};
-	    
-	    unlink("$ssh_dir/authorized_keys");
+
+	    if (-l "$ssh_dir") {
+		warn("$ssh_dir is a symlink, possible symlink attack!");
+	    } else {
+		unlink("$ssh_dir/authorized_keys");
+	    }
 	    system("chown $uid:$uid $homedir_prefix/$username");
 	    system("chown $uid:$uid $ssh_dir");
 

Modified: trunk/gforge/debian/changelog
===================================================================
--- trunk/gforge/debian/changelog	2009-11-30 16:31:45 UTC (rev 8450)
+++ trunk/gforge/debian/changelog	2009-11-30 16:33:34 UTC (rev 8451)
@@ -39,6 +39,7 @@
 
 gforge (4.8.1-3+) UNRELEASED; urgency=low
 
+  [ Olivier Berger ]
   * Fix copyright file to mention nusoap.
   * Fix location of Vcs-Bzr: sources repository.
   * Fix problem in use-snoopy-from-distro.dpatch containing .rej changes.
@@ -47,8 +48,11 @@
   * Add provides tag to control for fusionforge.
   * Change default system name to FusionForge instead of GForge.
 
- -- Olivier Berger <olivier.berger at it-sudparis.eu>  Sat, 14 Nov 2009 11:18:43 +0100
+  [ Roland Mas ]
+  * Fix for symlink attack (CVE-2009-3304).
 
+ -- Roland Mas <lolando at debian.org>  Mon, 23 Nov 2009 13:53:17 +0100
+
 gforge (4.8.1-3) unstable; urgency=low
 
   * New upstream snapshot from the 4.8 branch.  This includes fixes for

Modified: trunk/gforge/plugins/scmcvs/cronjobs/ssh_create.php
===================================================================
--- trunk/gforge/plugins/scmcvs/cronjobs/ssh_create.php	2009-11-30 16:31:45 UTC (rev 8450)
+++ trunk/gforge/plugins/scmcvs/cronjobs/ssh_create.php	2009-11-30 16:33:34 UTC (rev 8451)
@@ -4,6 +4,7 @@
  * GForge Cron Job
  *
  * The rest Copyright 2002-2005 (c) GForge Team
+ * Copyright (C) 2009  Sylvain Beucler
  * http://gforge.org/
  *
  * This file is part of GForge.
@@ -57,10 +58,16 @@
 		mkdir ($ssh_dir, 0755);
 	}
 
+	# Set the effective uid/gid to this user, so as to avoid symlink attacks
+	$userinfo = posix_getpwnam($username);
+	posix_setegid($userinfo['gid']);
+	posix_seteuid($userinfo['uid']);
 	$h8 = fopen("$ssh_dir/authorized_keys","w");
 	fwrite($h8,'# This file is automatically generated from your account settings.'."\n");
 	fwrite($h8,$ssh_key);
 	fclose($h8);
+	posix_seteuid(0);
+	posix_setegid(0);
 		
 	system("chown $username:users $homedir_prefix/$username");
 	system("chown $username:users $ssh_dir");




More information about the Fusionforge-commits mailing list