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^]
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]
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
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... ;-)
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.
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
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.
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]
Was vendor-sec contacted about this ?
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?
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.
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...
ebuild updated and moved to stable for all just needs GLSA now
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 :)
hi, yes, bug is public now (author released advisory... ;-) ) thanks for your work best regards florian
GLSA 200410-28