I have a use for sftp to run in a chroot jail.
Since sftp doesn't quite work properly for that, I did the
work to make it function like that.
This required two different changes:
sftpsh is a replacement for nologin. It
works like nologin except under certain circumstances --
where it will start up sftp-server.
The other part was to add an option to sftp-server.
the '-c' option causes sftp-server to chroot(".");chdir("/");
(the latter being to avoid chroot hole problems).
It's been a while since I've done anything security-critical,
so PLEASE feel free to audit/critique my code.
The changes for sftp-server.c and sftp-server.8 are as follows:
===================================================================
RCS file: RCS/sftp-server.c,v
retrieving revision 1.38
diff -u -r1.38 sftp-server.c
--- sftp-server.c 2002/11/10 22:56:08 1.38
+++ sftp-server.c 2002/11/11 04:01:02
@@ -1058,6 +1058,11 @@
ssize_t len, olen, set_size;
/* XXX should use getopt */
+ if(ac == 2 && strcmp(av[1],"-c") == 0 ){
+ chroot(".");
+ chdir("/"); /* get rid of '.' chroot hole */
+ setuid(getuid());
+ };
__progname = get_progname(av[0]);
handle_init();
===================================================================
===================================================================
RCS file: RCS/sftp-server.8,v
retrieving revision 1.1
diff -u -r1.1 sftp-server.8
--- sftp-server.8 2002/11/10 23:17:06 1.1
+++ sftp-server.8 2002/11/10 23:35:44
@@ -43,6 +43,10 @@
See
.Xr sshd 8
for more information.
+.Sh OPTIONS
+.Bl -tag -width CC
+.It Fl c
+chroot jail: (do a chroot and setuid(getuid()) when starting)
.Sh SEE ALSO
.Xr sftp 1 ,
.Xr ssh 1 ,
===================================================================
sftpsh.c is attached (83 lines including copyright)
Notes:
sftpsh needs to be installed setuid.
I don't have install scripts for it.
The location of sftp-server is hardwired into sftpsh.c .
sftpsh.c uses /proc/ppid/cmdline to check the name and pid of it's parent
No docs for sftpsh.c
Conditions for sftpsh calling sftp-server:
Parent process is sshd, and is uid-root.
parameters are: "-c /usr/libexec/sshd/sshd-server"
If sftp-server doesn't cooperate, you end up with a (potential) remote root exploit.
Perhaps instead of checking for a parameter of '-c' I should just check for euid==0?
--
Stephen Samuel +1(604)876-0426 sam...@bcgreen.com
http://www.bcgreen.com/~samuel/
Powerful committed communication, reaching through fear, uncertainty and
doubt to touch the jewel within each person and bring it to life.
--------------010100040908070307060303
Content-Type: text/plain;
name="sftpsh.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="sftpsh.c"
/*
* Copyright (c) 2002 Stephen Samuel. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* SFTP friendly replacement for nologin.c
*
* Notes:
* sftpsh needs to be installed setuid. (and added to /etc/shells)
* BUGS:
* I don't have install scripts for it.
* The location of sftp-server is hardwired into sftpsh.c .
* sftpsh.c uses /proc/ppid/cmdline to check the name and pid of it's parent
* Is there a clean, OS-independent way of doing this?
* No man page or docs
*/
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SSHD_CMD "/usr/sbin/sshd"
#define SFTP_SERVER "/usr/libexec/openssh/sftp-server"
void message(char* msg){
fprintf(stderr,"This account is currently not available.%s\n",msg);
exit(1);
};
main(int parc, char **parv){
int i;
char line[2000];
pid_t cpid, cmdfd,Pid=getpid(),pPid=getppid();
struct stat statbuf[1];
/*
* check to see if we're calling ftp-server
*/
if( parc !=3 || strcmp(parv[1],"-c")||strcmp(parv[2],SFTP_SERVER)){
message(""); /* should be the default 'oops' case */
}
sprintf(line,"/proc/%d/cmdline",pPid);
cmdfd=open(line,O_RDONLY);
if(cmdfd == -1){
/* couldn't open parent proc file */
message(" (cmdfd open failed)");
};
if( i=fstat(cmdfd, statbuf)){
message(" (fstat failed)");
};
/* Parent proc must be owned by root */
if( statbuf -> st_uid !=0 ){
message(" (non-root parent)");
}else{
i=read(cmdfd,line,1000);
if(i<1){
message(" (cmd read failed)");
};
/* append null */
line[i]=(char)0;
close(cmdfd);
/* command is sshd?? */
if(strcmp(line,SSHD_CMD)){
message(" (not sshd child)");
}
/* passed all tests... call sftp-server */
execl( SFTP_SERVER, SFTP_SERVER,"-c",NULL);
i=errno;
fprintf(stderr,"%s(%d)exec failed(%s)\n",parv[0],Pid,strerror(i));
exit(2);
}
};
--------------010100040908070307060303--
_______________________________________________
openssh-...@mindrot.org mailing list
http://www.mindrot.org/mailman/listinfo/openssh-unix-dev