Re: Chrooted sftp-server and /dev/null

2006-07-07 Thread Joshua Sandbrook
On Friday 23 June 2006 22:24, Joachim Schipper wrote:

 You could set up a named pipe (mkfifo(1)), and have a process
 continually drain it (cat /home/john/dev/null /dev/null ); however,
 while this would work for the most likely use (writing to /dev/null), it
 wouldn't allow for reading.
 I'm not sure if sftp-server ever reads from /dev/null, but it is not
 impossible. Strange errors will occur if this is the case.



Im thinking it might just be easier to make a copy of the /dev/null device, 
but i need to investigate and test this... 

 Yes, make sure you also set real uid. A small part of
 /usr/src/usr.sbin/tcpdump/privsep.c:

 /* Child - drop suid privileges */
 gid = getgid();
 uid = getuid();

 if (setresgid(gid, gid, gid) == -1)
 err(1, setresgid() failed);
 if (setresuid(uid, uid, uid) == -1)
 err(1, setresuid() failed);

 Do note that this is only necessary if the shell is suid and/or sgid;
 however, normal users don't have the rights to call chroot(2), so these
 additional priviliges are necessary.

 Also, you are aware that you perform chroot(), setresuid() and
 setresgid(), and only then execve()? This means that you'll need some
 binaries in the home directories...

 So, be aware that deleting a file or directory requires write priviliges
 on the parent directory; i.e., john can replace
 /home/john/bin/sftp-server by an arbitrary binary if john has write
 priviliges on his home directory, hence my suggestion to use /home
 (which is typically only writable by root) above.
 (An alternate solution is to make /home/john owned by root, group john,
 and with priviliges 0750; this would break too many things to be
 feasible if shells are allowed, but just might work if only considering
 sftp.)

 Finally, be aware of the many other options sshd allows, like various
 ways of tunneling. For the same reason as above, those cannot be
 disabled in /home/john/.ssh/authorized_keys only (disabling them there
 works iff the user cannot mess with this file, which is clearly not the
 case if the user has access to sftp). Either disable them sshd-wide or
 set AuthorizedKeysFile (see sshd_config(5)) to something like
 /home/.keys/%u/authorized_keys.
 Note that running any number of ssh daemons in parallel works just fine,
 subject to some caveats (they can, of course, not listen on the same
 ports on the same interfaces; they are quite CPU intensive; and random
 number quality may degrade if the pool is drained sufficiently fast).

   Joachim

I am going to write another program which is used to setup, check, and update 
the chroot environments with the right files and permissions. Im going to 
have it chown the home dirs to root/wheel, and there will only be a single 
writeable dir owned by the user ( which will contain their website files for 
example ).

Here is a copy of the code ive got so far... its by no means finished, or 
formatted in the proper way, or even checked over properly again:




#include stdio.h
#include stdlib.h
#include errno.h
#include string.h
#include syslog.h
#include stdarg.h
#include unistd.h
#include fcntl.h
#include sys/types.h
#include sys/wait.h
#include pwd.h

char home_dir[1024];
int argc;
char **argv;


void print_arguments(void);
void check_arguments(void);
void check_user(void);
char * find_end_part(char *buff);
void setup_env(void);

int
main(int _argc, char **_argv) {
char *exec_args[2];

argc = _argc;
argv = _argv;

openlog(jshell, LOG_PID | LOG_NDELAY, LOG_AUTH);

check_arguments();
check_user();

if (chroot(home_dir) != 0 || chdir(/) != 0) {
syslog(LOG_ERR, chroot(%s) failed: %s, home_dir, strerror(errno));
return 1;
}

/* drop privledges */
if (seteuid(getuid()) != 0 || setuid(getuid()) != 0) {
syslog(LOG_ERR, setuid(%d) failed: %s, getuid(), strerror(errno));
return 1;
}

exec_args[1] = NULL;
exec_args[0] = find_end_part(argv[2]);
execve(argv[2], exec_args, NULL);
syslog(LOG_ERR, execve failed);

return 1;
}

/* print arguments to syslog */
void
print_arguments(void) {
int x;
for (x = 0; x  argc; x++) {
syslog(LOG_ERR, %d arg is '%s', x, argv[x]);
}
}

/* 
 *  for now we only allow -c /usr/libexec/sftp-server as an argument 
 */
void
check_arguments(void) {

/* compare second argument ( should be -c ) */
if (argc != 3 || strcmp(-c, argv[1]) != 0) {
syslog(LOG_ERR, invalid arguments\n);
print_arguments();
exit(1);
}

/* compare third argument */
if (strcmp(/usr/libexec/sftp-server, argv[2]) != 0) {
syslog(LOG_ERR, invalid arguments\n);
print_arguments();
exit(1);
}

}

/* 
 * check the user has some sane permissions and settings 
 * and what not on their home dir.
 */
void
check_user(void) {

struct passwd *pw = NULL;

/*
 * do we bother checking for a root login? 
 * why would root be 

Re: Chrooted sftp-server and /dev/null

2006-06-23 Thread Joachim Schipper
On Fri, Jun 23, 2006 at 12:00:17PM +1200, Joshua Sandbrook wrote:
 On Thursday 22 June 2006 22:26, Joachim Schipper wrote:
  A quick grep through /usr/src/usr.bin/ssh suggests that ssh (and, most
  likely, sftp) interacts with /dev/null quite a bit. It might be possible
  to change the code to work without, but that would take quite a bit of
  work I fear.
 
  An alternative hack would be to change sftp directly; in this case, it
  can safely open /dev/null and then call chroot() at the appropriate
  time. OTOH, you have a custom patch that you should apply at the
  appropriate time and place, which, too, has its disadvantages.
 
  Also, be *very* careful in writing the shell, as it must be suid root
  for what you want it to do... this, in fact, suggests that the best
  solution might be to write a trivial shell and just have
  /home/*/dev/null. Or, for that matter, /home/dev/null and chroot into
  /home.

 Thanks for the reply...
 
 It is sftp-server that tries to open /dev/null. 
 
 As I dont want to modify sftp-server or anything like that, I think im going 
 to just populate each chroot environment with a /dev/null. However, as I dont 
 want /home to have any devices on it, is there a way to have some sort of 
 file type that simply throws the data away like /dev/null does?

You could set up a named pipe (mkfifo(1)), and have a process
continually drain it (cat /home/john/dev/null /dev/null ); however,
while this would work for the most likely use (writing to /dev/null), it
wouldn't allow for reading.
I'm not sure if sftp-server ever reads from /dev/null, but it is not
impossible. Strange errors will occur if this is the case.

 As for the shell, Yep, I am being carefull with it.. all the shell actaully 
 does, is checks if the arguments given to it is 
 '-c /usr/libexec/sftp-server', and if it is, it then chroots to the users 
 home dir, and then it sets effective uid to the uid that called the shell, 
 and then it executes /usr/libexec/sftp-server. Not much code at all.
 
 I want to research more into possible security hassles ( like
 /home/foo/.ssh ) and stuff like that later on. Any suggestions in this
 area? ( security )

Yes, make sure you also set real uid. A small part of
/usr/src/usr.sbin/tcpdump/privsep.c:

/* Child - drop suid privileges */
gid = getgid();
uid = getuid();

if (setresgid(gid, gid, gid) == -1)
err(1, setresgid() failed);
if (setresuid(uid, uid, uid) == -1)
err(1, setresuid() failed);

Do note that this is only necessary if the shell is suid and/or sgid;
however, normal users don't have the rights to call chroot(2), so these
additional priviliges are necessary.

Also, you are aware that you perform chroot(), setresuid() and
setresgid(), and only then execve()? This means that you'll need some
binaries in the home directories...

So, be aware that deleting a file or directory requires write priviliges
on the parent directory; i.e., john can replace
/home/john/bin/sftp-server by an arbitrary binary if john has write
priviliges on his home directory, hence my suggestion to use /home
(which is typically only writable by root) above.
(An alternate solution is to make /home/john owned by root, group john,
and with priviliges 0750; this would break too many things to be
feasible if shells are allowed, but just might work if only considering
sftp.)

Finally, be aware of the many other options sshd allows, like various
ways of tunneling. For the same reason as above, those cannot be
disabled in /home/john/.ssh/authorized_keys only (disabling them there
works iff the user cannot mess with this file, which is clearly not the
case if the user has access to sftp). Either disable them sshd-wide or
set AuthorizedKeysFile (see sshd_config(5)) to something like
/home/.keys/%u/authorized_keys.
Note that running any number of ssh daemons in parallel works just fine,
subject to some caveats (they can, of course, not listen on the same
ports on the same interfaces; they are quite CPU intensive; and random
number quality may degrade if the pool is drained sufficiently fast).

Joachim



[Fwd: Re: Chrooted sftp-server and /dev/null]

2006-06-23 Thread Richard Wilson

Joshua Sandbrook wrote:


Gidday

Im writing a shell at the moment that chroots into a users home dir and then 
runs only the sftp-server program ( which is in the uses home dir ).


Anyway, it wont work unless /dev/null is present in the chroot... 

I am using execve to run sftp-server, and I am wondering if it has something 
to do with stdout / stdin / stderr fd's being closed on execve? 

Can anyone help me here? 

Thanks, 
	Josh


  


/de-lurk

Alternatively, might something like rssh be useful?

http://pizzashack.org/rssh/


This is a shell, designed to only allow scp/sftp/et al, but not allow 
any sort of command execution in the traditional sense. It also supports 
chroot.


The only small fly in the ointment, is that according to 
http://pizzashack.org/rssh/platforms.shtml it doesn't work on *BSD, as 
it requires the missing wordexp() function. However, the page dates back 
to 2003, and I haven't the skills to check if this is still the case...


Don't know if this helps or not, but I thought I'd throw it into the mix :-)

Si1entDave



Re: [Fwd: Re: Chrooted sftp-server and /dev/null]

2006-06-23 Thread Bastiaan Jacques
On Friday 23 June 2006 16:42, Richard Wilson wrote:
 The only small fly in the ointment, is that according to
 http://pizzashack.org/rssh/platforms.shtml it doesn't work on *BSD,
 as it requires the missing wordexp() function. However, the page
 dates back to 2003, and I haven't the skills to check if this is
 still the case...

At least FreeBSD now has this call, but OpenBSD does not. However, 
scponly [1] compiles on OpenBSD out of the box.

Bastiaan

[1] http://www.sublimation.org/scponly/



Re: Chrooted sftp-server and /dev/null

2006-06-22 Thread Joachim Schipper
On Wed, Jun 21, 2006 at 09:41:42AM +1200, Joshua Sandbrook wrote:
 Gidday
 
 Im writing a shell at the moment that chroots into a users home dir and then 
 runs only the sftp-server program ( which is in the uses home dir ).
 
 Anyway, it wont work unless /dev/null is present in the chroot... 
 
 I am using execve to run sftp-server, and I am wondering if it has something 
 to do with stdout / stdin / stderr fd's being closed on execve? 
 
 Can anyone help me here? 

Well, since nobody else seems to respond...

If you can set it up in a controlled testing environment, you could
ktrace(1) it. This would tell you, at the very least, what program
actually opens /dev/null.

A quick grep through /usr/src/usr.bin/ssh suggests that ssh (and, most
likely, sftp) interacts with /dev/null quite a bit. It might be possible
to change the code to work without, but that would take quite a bit of
work I fear.

An alternative hack would be to change sftp directly; in this case, it
can safely open /dev/null and then call chroot() at the appropriate
time. OTOH, you have a custom patch that you should apply at the
appropriate time and place, which, too, has its disadvantages.

Also, be *very* careful in writing the shell, as it must be suid root
for what you want it to do... this, in fact, suggests that the best
solution might be to write a trivial shell and just have
/home/*/dev/null. Or, for that matter, /home/dev/null and chroot into
/home.

Joachim



Re: Chrooted sftp-server and /dev/null

2006-06-22 Thread Joshua Sandbrook
Thanks for the reply...

It is sftp-server that tries to open /dev/null. 

As I dont want to modify sftp-server or anything like that, I think im going 
to just populate each chroot environment with a /dev/null. However, as I dont 
want /home to have any devices on it, is there a way to have some sort of 
file type that simply throws the data away like /dev/null does?

As for the shell, Yep, I am being carefull with it.. all the shell actaully 
does, is checks if the arguments given to it is 
'-c /usr/libexec/sftp-server', and if it is, it then chroots to the users 
home dir, and then it sets effective uid to the uid that called the shell, 
and then it executes /usr/libexec/sftp-server. Not much code at all.

I want to research more into possible security hassles ( like /home/foo/.ssh ) 
and stuff like that later on. Any suggestions in this area? ( security )

Cheers, 
Josh

On Thursday 22 June 2006 22:26, Joachim Schipper wrote:
 Well, since nobody else seems to respond...

 If you can set it up in a controlled testing environment, you could
 ktrace(1) it. This would tell you, at the very least, what program
 actually opens /dev/null.

 A quick grep through /usr/src/usr.bin/ssh suggests that ssh (and, most
 likely, sftp) interacts with /dev/null quite a bit. It might be possible
 to change the code to work without, but that would take quite a bit of
 work I fear.

 An alternative hack would be to change sftp directly; in this case, it
 can safely open /dev/null and then call chroot() at the appropriate
 time. OTOH, you have a custom patch that you should apply at the
 appropriate time and place, which, too, has its disadvantages.

 Also, be *very* careful in writing the shell, as it must be suid root
 for what you want it to do... this, in fact, suggests that the best
 solution might be to write a trivial shell and just have
 /home/*/dev/null. Or, for that matter, /home/dev/null and chroot into
 /home.

   Joachim



Re: Chrooted sftp-server and /dev/null

2006-06-21 Thread Joshua Sandbrook
Can anyone help here?

Ive played wih fcntl's FD_CLOEXEC and what not.. it was set to 0, and yeah...

If someone can help solve this mystery then there is one less file required in 
the chroot environment. A cleaner scponly shell :)

On Wednesday 21 June 2006 09:41, Joshua Sandbrook wrote:
 Gidday

 Im writing a shell at the moment that chroots into a users home dir and
 then runs only the sftp-server program ( which is in the uses home dir ).

 Anyway, it wont work unless /dev/null is present in the chroot...

 I am using execve to run sftp-server, and I am wondering if it has
 something to do with stdout / stdin / stderr fd's being closed on execve?

 Can anyone help me here?

 Thanks,
   Josh