[Fusionforge-commits] r8459 - in branches/Branch_4_5/gforge: cronjobs/cvs-cron deb-specific

Roland Mas lolando at libremir.placard.fr.eu.org
Thu Dec 3 14:20:53 CET 2009


Author: lolando
Date: 2009-12-03 14:20:52 +0100 (Thu, 03 Dec 2009)
New Revision: 8459

Modified:
   branches/Branch_4_5/gforge/cronjobs/cvs-cron/ssh_create.php
   branches/Branch_4_5/gforge/deb-specific/ssh_dump_update.pl
Log:
Backported fix for CVE-2009-3304

Modified: branches/Branch_4_5/gforge/cronjobs/cvs-cron/ssh_create.php
===================================================================
--- branches/Branch_4_5/gforge/cronjobs/cvs-cron/ssh_create.php	2009-12-02 13:30:04 UTC (rev 8458)
+++ branches/Branch_4_5/gforge/cronjobs/cvs-cron/ssh_create.php	2009-12-03 13:20:52 UTC (rev 8459)
@@ -4,6 +4,7 @@
  * GForge Cron Job
  *
  * The rest Copyright 2002-2005 (c) GForge Team
+ * Copyright (C) 2009  Sylvain Beucler
  * http://gforge.org/
  *
  * @version   $Id$
@@ -53,10 +54,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");

Modified: branches/Branch_4_5/gforge/deb-specific/ssh_dump_update.pl
===================================================================
--- branches/Branch_4_5/gforge/deb-specific/ssh_dump_update.pl	2009-12-02 13:30:04 UTC (rev 8458)
+++ branches/Branch_4_5/gforge/deb-specific/ssh_dump_update.pl	2009-12-03 13:20:52 UTC (rev 8459)
@@ -4,8 +4,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 protects 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;
@@ -56,10 +113,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";
@@ -97,8 +156,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");
 




More information about the Fusionforge-commits mailing list