Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!

Bug 66988

Summary: app-shells/rssh formatstring vulnerability
Product: Gentoo Security Reporter: Florian Schilhabel (RETIRED) <ruth>
Component: VulnerabilitiesAssignee: Gentoo Security <security>
Status: RESOLVED FIXED    
Severity: major    
Priority: High    
Version: unspecified   
Hardware: All   
OS: All   
URL: http://rssh.sourceforge.net/
Whiteboard: B2 [glsa]
Package list:
Runtime testing required: ---

Description Florian Schilhabel (RETIRED) gentoo-dev 2004-10-10 09:31:31 UTC
Program: rssh
Homepage: http://rssh.sourceforge.net/
Vulnerable Versions: current version v2.2.1; others not tested
Risk: High
Impact: remote formatstring vulnerability / remote root
Author contacted: yes (10/10/2004)

Introduction

I have discovered a remote exploitable formatstring bug in rssh.

description:

rssh is a restricted shell for use with OpenSSH, allowing only scp and/or sftp.
For example, if you have a server which you only want to allow users to copy files off of via scp, without providing shell access,
you can use rssh to do that. For a list of platforms on which rssh is known to work, see the Platform Support Page.

--- login procedure; client view ---
[flo@leela][tmp:exec](~) $ ssh john@192.168.1.14 sftp %s%s%s%s
john@192.168.1.14's password:

This account is restricted by rssh.
Allowed commands: sftp cvs rdist

If you believe this is in error, please contact your system administrator.

[flo@leela][tmp:exec](~) $
-- end client view ---

-- login procedure; server view --
Oct  9 23:19:28 superman rssh[30932]: allowing sftp to all users
Oct  9 23:19:28 superman rssh[30932]: allowing cvs to all users
Oct  9 23:19:28 superman rssh[30932]: allowing rdist to all users
Oct  9 23:19:28 superman rssh[30932]: setting umask to 022
Oct  9 23:19:28 superman rssh[30932]: user john attempted to log in with a shell
Oct  9 23:20:17 superman rssh[30995]: allowing sftp to all users
Oct  9 23:20:17 superman rssh[30995]: allowing cvs to all users
Oct  9 23:20:17 superman rssh[30995]: allowing rdist to all users
Oct  9 23:20:17 superman rssh[30995]: setting umask to 022
Oct  9 23:20:17 superman rssh[30995]: user john attempted to execute forbidden commands
Oct  9 23:20:17 superman rssh[30995]: command: sftp command: %s^]
Comment 1 Florian Schilhabel (RETIRED) gentoo-dev 2004-10-10 09:31:31 UTC
Program: rssh
Homepage: http://rssh.sourceforge.net/
Vulnerable Versions: current version v2.2.1; others not tested
Risk: High
Impact: remote formatstring vulnerability / remote root
Author contacted: yes (10/10/2004)

Introduction

I have discovered a remote exploitable formatstring bug in rssh.

description:

rssh is a restricted shell for use with OpenSSH, allowing only scp and/or sftp.
For example, if you have a server which you only want to allow users to copy files off of via scp, without providing shell access,
you can use rssh to do that. For a list of platforms on which rssh is known to work, see the Platform Support Page.

--- login procedure; client view ---
[flo@leela][tmp:exec](~) $ ssh john@192.168.1.14 sftp %s%s%s%s
john@192.168.1.14's password:

This account is restricted by rssh.
Allowed commands: sftp cvs rdist

If you believe this is in error, please contact your system administrator.

[flo@leela][tmp:exec](~) $
-- end client view ---

-- login procedure; server view --
Oct  9 23:19:28 superman rssh[30932]: allowing sftp to all users
Oct  9 23:19:28 superman rssh[30932]: allowing cvs to all users
Oct  9 23:19:28 superman rssh[30932]: allowing rdist to all users
Oct  9 23:19:28 superman rssh[30932]: setting umask to 022
Oct  9 23:19:28 superman rssh[30932]: user john attempted to log in with a shell
Oct  9 23:20:17 superman rssh[30995]: allowing sftp to all users
Oct  9 23:20:17 superman rssh[30995]: allowing cvs to all users
Oct  9 23:20:17 superman rssh[30995]: allowing rdist to all users
Oct  9 23:20:17 superman rssh[30995]: setting umask to 022
Oct  9 23:20:17 superman rssh[30995]: user john attempted to execute forbidden commands
Oct  9 23:20:17 superman rssh[30995]: command: sftp command: %s^]ÿÿ¿^Hü^D^H V^A@Pà^D^HUà^D^H÷^Cvðÿ^E@àN^L@ t^G@0% @ðw^D@V\211^D^Hðõ^G@@è^L@\206\211^D^HÐþ^F@Ð9^H@ \222^D@ <^E@À;^H@\200ð^L@
-- end server view --

remote attacker controls formatstring; remote exploitation possible...

-- code log.c --
 void log_msg( char *msg, ... )
{

[snip]
	
	retc = vsnprintf( format_temp, length, msg, arglist );

	/* 
	 * Check retc to make sure it fit account for differences in libc
	 * versions (grumble)...  Per C99, retc is # of chars that WOULD have
	 * been copied if format_temp was large enough, so make the buffer
	 * that size.
	 */
	if ( retc > length ){

		if ( (format_temp = (char *)realloc( format_temp, retc + 1 )) 
				== NULL ){
			syslog(LOG_ERR, 
				"Could not allocate mem in log_msg(), log.c");
			exit(1);
		}
		vsnprintf( format_temp, retc + 1, msg, arglist );
	}
	
[snip]

	syslog((facility | level), format_temp);
}
-- end code format.c --

-- patch --

--- ./rssh-2.2.1/log.c  2003-02-13 07:21:58.000000000 +0100
+++ ./rssh-2.2.1_new/log.c      2004-10-10 18:04:29.399286160 +0200
@@ -188,6 +188,6 @@

        /* clean up arglist and log the string */
        va_end( arglist );
-       syslog((facility | level), format_temp);
+       syslog((facility | level), "%s", format_temp);
 }


-- end patch --

aditionally, the impact is much higher:
look at this code:

--  rssh_chroot_helper.c --
[snip]
	/* make sure we can change directory to the user's dir */
	if ( chdir(argv[3]) == -1 ){
		log_msg("could not cd to user's home dir: %s", argv[3]);
		if ( chdir("/") )
			ch_fatal_syscall("chdir()", "/", strerror(errno));
	}
[snip]
--  end rssh_chroot_helper.c --

-rwsr-xr-x  1 root 12148 Oct  9 21:36 /usr/lib/misc/rssh_chroot_helper

-- demonstration --
$ ./rssh_chroot_helper AAAA`perl -e 'print "%x"x60'` BB CC DD

-- syslog:

Oct 10 18:03:13 leela rssh_chroot_helper[12299]: stat() failed, 804910cbffff5143804b080a3bffff614040012280bffff5288048a05804910c80491babffff7be4011fae7040012280bffff5b88048c8680491babffff7be4011fae7040034c544012e374880400392e240034c544012e30843bffff5b84000a34044012e624400cb7d040028000400cb7d54003eae034012e6244400371b94002fe444012e30804012e624bffff5e84000a34004012e3084012e3080bffff5e84003e8805bffff614bffff62c804885004000a340: No such file or directory

-- end syslog

note, however, that at this point rssh_chroot_helper has already dropped root privileges,
so a shellcode must do a call to setreuid (which is not a real problem).

in fact, successful exploitation of this bug leads to a remote root compromise of the affected machine

best regards
florian [rootshell]
Comment 2 Florian Schilhabel (RETIRED) gentoo-dev 2004-10-10 10:29:56 UTC
hi again,
after reading the code more in-deep, i found, that 
rssh_chroot_helper
drops privileges with setuid()
therefore it is impossible to re-gain root privileges with this bug.
nevertheless, the remote vulnerability still exists...

author has responded and will publish an updated version in about a week.

best regards
Comment 3 Florian Schilhabel (RETIRED) gentoo-dev 2004-10-10 10:36:19 UTC
ah, one more:
the call to log_msg happens before the suid_helper drops privileges.
therefore my first advice is true...
sorry for spamming ;-)

regards florian

better think before writing... ;-)
Comment 4 Thierry Carrez (RETIRED) gentoo-dev 2004-10-10 10:45:46 UTC
OK, we'll just keep the remote arbitrary code execution with user rights (rssh bypass). Waiting for upstream.

Note that we might want to coordinate this one between vendor-sec, upstream and us.
Comment 5 Florian Schilhabel (RETIRED) gentoo-dev 2004-10-10 11:40:48 UTC
agreed, after discussion with koon.
at least also affected are 
debian testing 
debian unstable

if other distributions ship rssh? i don't know...

regards
florian

Comment 6 Kurt Lieber (RETIRED) gentoo-dev 2004-10-11 05:12:47 UTC
florian -- I'd like to send this info on to vendor-sec to make them aware of the issue.  Can you confirm the following:

* everything you stated in your original bug report is still accurate (esp. the part about the remote root compromise).  If it's no longer accurate, can you please post a follow-up comment that contains *complete* accurate details?  I need something I can literally copy and paste into an email to vendor-sec.  If it *is* a remote root compromise, any chance you can post an example exploit?
* the author has confirmed that this is a real bug

Thanks.
Comment 7 Florian Schilhabel (RETIRED) gentoo-dev 2004-10-11 07:59:59 UTC
hi,
as i already told koon:
this is _not_ a remote root compromise bug.
rssh is used as an replacement shell, to restrict ssh users to special commands:
scp, sftp, csv, rdist and rsync

first:
the affected function in log.c:

void log_msg( char *msg, ... )
{

	char    *format_temp;
	va_list arglist;
	int     length;        /* length of msg */
	int     retc;          /* return code */

	/* 
	 * make a guess how big the message will be -- initially we'll allow
	 * 50 characters for formatting variable args
	 */
	length = 50 + strlen( msg );
	if ( (format_temp = (char *)malloc( length )) == NULL){
		syslog(LOG_ERR, "Could not allocate mem in log_msg(), log.c");
		exit(1);
	}
	memset( format_temp, 0, length );

	/* try to print msg to buffer, until we succeed or fail conclusively */
	va_start( arglist, msg );
	retc = vsnprintf( format_temp, length, msg, arglist );

	/* 
	 * Check retc to make sure it fit account for differences in libc
	 * versions (grumble)...  Per C99, retc is # of chars that WOULD have
	 * been copied if format_temp was large enough, so make the buffer
	 * that size.
	 */
	if ( retc > length ){

		if ( (format_temp = (char *)realloc( format_temp, retc + 1 )) 
				== NULL ){
			syslog(LOG_ERR, 
				"Could not allocate mem in log_msg(), log.c");
			exit(1);
		}
		vsnprintf( format_temp, retc + 1, msg, arglist );
	}
	/* if retc == -1, we must be compiled under pre-C99 libc */
	while ( retc == -1 ){
		length += 50;
		if ( (format_temp = (char *)realloc( format_temp, length )) 
		        == NULL ){
			syslog(LOG_ERR,
				"Could not allocate mem in log_msg(), log.c");
			exit(1);
		}	
		memset( format_temp, 0, length );
		retc = vsnprintf( format_temp, length, msg, arglist );
	}

	/* clean up arglist and log the string */
	va_end( arglist );
	syslog((facility | level), format_temp);
}

as you see, the string given to syslog() is clearly an format string bug.
this function is called from two binaries, making them both vulnerable:
rssh and rssh_chroot_helper.
notice, that rssh_chroot_helper is suid root...
if a user gives an 'forbidden command', this command is logged via syslog.
(the affected function...)
at this point, an attacker is able to completely break out of chroot() and gain a full shell with the privileges of an regular user.
that means, a full circumvention of rssh.
having a closer look at rssh_chroot_helper.c, i noticed, that if

-- snip --	
if ( stat(argv[1], &s) == -1 )
		ch_fatal_syscall("stat()", argv[1], strerror(errno));
-- snip --

the stat() fails, a message is logged via the affected function.
fortunately, ch_fatal_syscall() drops privileges with setuid() before calling
the affected function;
according to man setuid() there is no way to re-establish root-privileges for a program after doing this.
if the author would have called seteuid() instead, then this would be root compromise...

-- snip --
void ch_fatal_syscall( char *func, char *arg, char *strerr )
{

	/* drop privileges */
	if ( !geteuid() ) setuid(getuid());
	ch_start_logging();

	/* log error */
	log_msg("%s failed, %s: %s", func, arg, strerr);
	log_close();
	exit(1);
}
-- snip --

and this is, what i first overlooked... 
so the affected function is clearly called as the user who is calling this binary.

what remains is the remote exploitability of this bug.
after a successful authentication via ssh(!!!), sshd calls users shell.
(given in /etc/passwd)
if the command given to rssh is malicious (a formatstring) the user can gain a full shell with this.

2nd:
the author has already replied and confirmed the existence of this bug.
author will release an updated package within one week.

rgrd: example exploit:
do you want me to write a real exploit for this issue? ;-)

best regards
florian [rootshell]
Comment 8 Thierry Carrez (RETIRED) gentoo-dev 2004-10-20 01:11:46 UTC
Was vendor-sec contacted about this ?
Comment 9 Kurt Lieber (RETIRED) gentoo-dev 2004-10-20 04:31:08 UTC
yes, but I can't coordinate a release date until I have a patch to provide them as well.  Florian -- any word from the author?  Would he be willing to give us the patch ahead of time so I can coordinate w/ vendor-sec on this issue and give them a chance to prepare new packages?
Comment 10 Matthias Geerdsen (RETIRED) gentoo-dev 2004-10-24 09:09:29 UTC
http://www.pizzashack.org/rssh/security.shtml

Oct 23, 2004

Florian Schilhabel has identified a format string bug which can allow an attacker to run arbitrary code from an account configured to use rssh. In general the risk is low, as in most cases the user can only compromise their own account. The risk is mittigated by the fact that before this bug can be exploited, the user must log in successfully through ssh. This means that either the user is known, or that the system is already compromised.

However, on some older systems with broken implementations of the setuid() family of functions, a root compromise may be possible with certain configurations of rssh. Specifically, if rssh is configured to use a chroot jail, it will exec() rssh_chroot_helper, which must be setuid root in order to call chroot(). Normally, rssh_chroot_helper calls setuid(getuid()) and drops privileges before any of the logging functions are called, making a root compromise impossible on most systems. However, some older systems which handle saved UIDs improperly may be vulnerable to a root compromise. Linux in particular is not vulnerable to this, nor should modern POSIX-compliant Unix variants be. POSIX defines that the setuid() system call will set all UIDs (UID, saved UID, and effective UID) the specified UID if it is called with root privileges. Therefore in general, a root compromise is not possible, and I am not specifically aware of any systems on which one is possible.

The 2.2.2 release of rssh fixes this string format vulnerability. I have also gone over the code to make sure that no other such vulnerabilities exist. In addition to fixing this problem, rssh contains some new code to help identify certain problems for debugging problems when rssh fails. Additional logging of error conditions is performed.
Comment 11 Thierry Carrez (RETIRED) gentoo-dev 2004-10-25 00:32:26 UTC
Apparently author won't provide the patch... and prefers to release advisory on its own. I propose to open this since it's now public. Florian, please confirm.

vapier || max : please bump rssh to 2.2.2...
Comment 12 SpanKY gentoo-dev 2004-10-25 05:32:46 UTC
ebuild updated and moved to stable for all

just needs GLSA now
Comment 13 Thierry Carrez (RETIRED) gentoo-dev 2004-10-25 06:30:14 UTC
vapier: bad boy, you opened it without reporter consent.

I refrain from calling a global developer vote to revoke you since it was probably OK to open it :)

Comment 14 Florian Schilhabel (RETIRED) gentoo-dev 2004-10-25 07:29:19 UTC
hi,
yes, bug is public now (author released advisory... ;-) )
thanks for your work

best regards
florian
Comment 15 Thierry Carrez (RETIRED) gentoo-dev 2004-10-27 08:29:57 UTC
GLSA 200410-28