On Sun, 2018-01-07 at 18:41 +0000, halfdog wrote:> Hello list, > > I created a page to demonstrate, what would happen when chroot > root directory is writeable. In fact, code execution is possible > already, when only /etc and /bin are writable. I also tried to > escape the chroot jail, but that did not work for non-root users. > > As the 2009 CVE activities mention, that creating hardlinks > from outside gives trivial chroot, I showed that any cooperating > access from the outside - no matter if it is the same user or > another one - leads to root privilege escalation, even without > hardlinks, just using the default behaviour of any shared linked > SUID binary. > > hd > > [0] > https:///www.halfdog.net/Security/2018/OpensshSftpChrootCodeExecution > /Thank you for the article describing this issue in understandable manner. What struck my attention is the reading of the /etc/ssh/sshrc from chroot. Is it even correct that OpenSSH is searching for the /etc/ssh/sshrc file AFTER the chroot? No, I am not advocating the writable chroots, but is sounds to me wrong, or at least nothing I would expect. Even though it is not exploitable out of the box, it might be if one chooses "wrong" names for users directories (well ... etc/ might not be too uncommon). Regards, -- Jakub Jelen Software Engineer Security Technologies Red Hat, Inc.
Dear OpenSSH Developers, I believe that many admins would appreciate a functionality similar to the Apache HTTP Server's "DocumentRoot" in SFTP. I am sure many admins did and will try to use chroot instead as the "close enough match, should work" solution - opening up multiple cans of worms. OpenSSH does not *need* DocumentRoot. But I think it would greatly ease the work of overloaded admins and it could increase security by reducing the number of ill-configured SFTP servers. I would gladly implement this functionality if somebody is willing to sponsor me in integrate it in the next portable OpenSSH release. I am unmotivated to move forward without a sponsor as my previous patch [1] is ready for integration for many weeks and I got no reply for my requests, not even a "No, stupid.". Best wishes: Elmar [1] https://bugzilla.mindrot.org/show_bug.cgi?id=1844> ... or at least nothing I would expect. ...
Jakub Jelen writes:> On Sun, 2018-01-07 at 18:41 +0000, halfdog wrote: > > Hello list, > > > > I created a page to demonstrate, what would happen when chroot > > root directory is writeable. In fact, code execution is possible > > already, when only /etc and /bin are writable. I also tried to > > escape the chroot jail, but that did not work for non-root users. > > > > As the 2009 CVE activities mention, that creating hardlinks > > from outside gives trivial chroot, I showed that any cooperating > > access from the outside - no matter if it is the same user or > > another one - leads to root privilege escalation, even without > > hardlinks, just using the default behaviour of any shared linked > > SUID binary. > > > > hd > > > > [0] > > https:///www.halfdog.net/Security/2018/OpensshSftpChrootCodeExecution > > / > > Thank you for the article describing this issue in understandable > manner. What struck my attention is the reading of the /etc/ssh/sshrc > from chroot. > > Is it even correct that OpenSSH is searching for the /etc/ssh/sshrc > file AFTER the chroot?Yes, definitely - on Ubuntu Xenial and Debian stretch. Here is, how you can test yourself: * Connect to the test machine as root * Find the main SSH process, usually something like: root 752 0.0 0.1 55184 2788 ? Ss 2017 0:00 /usr/sbin/sshd -D * Use "strace -o trace.txt -s256 -f -p [pid]" * Login via sftp and then terminate strace * Search the file: grep -E -e '(chroot|open|lstat|stat)\(' trace.txt Some line should look like: 906 chroot("/var/lib/sftp") = 0 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) 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) * Loading of sshrc - really bad: 907 stat("/etc/ssh/sshrc", 0x7fff75547460) = -1 ENOENT (No such file or directory) * 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)> No, I am not advocating the writable chroots, but is sounds to me > wrong, or at least nothing I would expect. Even though it is not > exploitable out of the box, it might be if one chooses "wrong" names > for users directories (well ... etc/ might not be too uncommon).It is really bad from software design perspective because it indicates, that code intended for shell login is also execututed in seemingly unrelated context. If you take the pessimist's view: if ".sshrc" execution deactivation was missed, what else could be there with unexpected behavior? hd
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> 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) > > * 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.> * 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 Regards, -- Jakub Jelen Software Engineer Security Technologies Red Hat, Inc.