SFTP chroot: Writable root
halfdog
me at halfdog.net
Thu Jan 11 06:17:08 AEDT 2018
Jakub Jelen writes:
> On Tue, 2018-01-09 at 21:21 +0000, halfdog wrote:
> > [...]
> >
> > There are multiple weaknesses to be seen:
> >
> > * Ssh searches for /proc/[pid]/fd: I do not know, how sftp would
> > react, when that directory is found, but it is not nice, that
> > a hypothetical user "proc" could influence login behavior of
> > other processes
> >
> > 907 open("/proc/907/fd", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)
> > = -1 ENOENT (No such file or directory)
>
> This is just part of the closefrom() procedure [1] -- it searches for
> open file descriptor and if it finds them, it tries to close them. I
> don't think there is any straightforward way to exploit it.
> [1] https://github.com/openssh/openssh-portable/blob/master/openbsd-com
> pat/bsd-closefrom.c#L79
Thanks for looking up the reference. Well, there is a straight
forward way to exploit that, as the code does not check the return
code from close. Just create empty directories named /proc/[pid]/fd
for pid 1..2^16 and openssh will fail to close the fds. Then try
to get hold on them at another location.
I'll try to combine that with the sshrc to see, if I can get them
there.
> > Same argument for:
> >
> > 906 stat("/usr/lib/openssh/sftp-server", 0x7fff75547e00) = -1
> > ENOENT (No such file or directory)
> >
> > (When found, it is still not executed in sftp-internal mode)
I guess, this is one of the cases in non-internal mode, that the
sshd_config(5) manual page refers to "For safety, it is very important
that the directory hierarchy be prevented from modification by
other processes on the system (especially those outside the jail)."
... only that this should be security not safety?
> > * Loading of sshrc - really bad:
> >
> > 907 stat("/etc/ssh/sshrc", 0x7fff75547460) = -1 ENOENT (No such
> > file or directory)
>
> This can be a real problem from my point of view.
This is a real problem
> > * Search for other /etc files - I would not bet, that the passwd
> > parser was hardened against malicious input. Simply not a use case.
> >
> > 895 open("/etc/localtime", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such
> > file or directory)
> > 895 open("/etc/passwd", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such
> > file or directory)
> > 895 open("/etc/group", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such
> > file or directory)
> >
> > * This is also seems not really nice: if the target directory does
> > not
> > exist, login does not stop. But maybe it is a requirement, e.g.
> > to support login to users without having their own home directory.
> >
> > 907 chdir("/home/build") = -1 ENOENT (No such file or
> > directory)
>
> This is quite expected, that in chroot, there might not be the real
> home directory. Outside of chroot, it would be fatal error [2]. I don't
> think there is a way to misuse it in some way.
>
> [2] https://github.com/openssh/openssh-portable/blob/master/session.c#L
> 1586
>From the sftp-traces I analyzed, I would come to the same conclusion.
But with chrooted ssh, the failing to chdir() still did not stop
sshd from searching for file - now at the wrong location.
847 chdir("/home/build") = -1 ENOENT (No such file or directory)
...
847 stat(".ssh/rc", 0x7ffd2312e9b0) = -1 ENOENT (No such file or directory)
At the current state, this is also not exploitable - but it
demonstrates a design flow in a code-path intended for code
execution - meaning a very critical code path. This is a high
risk if circumstances change in next releases. For example, some
future version may add some "legal-stuff-module" required to show
"Log off immediately ... bla bla bla". And to build that text
in appropriate client language, ssh changes working directory
to /tmp to build the message - motd for login works quite that
way. And now a failure to chdir, e.g. because NFS is temporarily
unavailable will give code execution to that user, who left a
world-read/executable /tmp/.ssh/rc file.
hd
More information about the openssh-unix-dev
mailing list