Unprivileged Chroot()
lwn.net
lwn.net
Try running `unshare -m` to see what it's like in "just" a mount namespace.
4084 2021-03-02 01:08:24.055 fatal: safely_chroot: stat("C:\\sftpjail"): No such file or directoryWhy? Oh that makes sense. Wait! Abysmal Security Nightmare! Nooooooo Don't do that, Pleeeeeeease.
One of the main reason is that:
1. It increases the attack surface.
2. At least currently PR_SET_NO_NEW_PRIVS must not be relied on to be perfect for security. Must use cases use it as an additional security layer, but the chroot patch uses it as a fundamental required to be perfect building block.
3. As far as I can tell the benefit it gives is not worth the increased attack surface even if PR_SET_NO_NEW_PRIVS would work perfectly. But I might be wrong.
Honestly the additional constraints it puts on chroot are good and I believe should be fulfilled for must use cases of chroot. So I think best would be either a "CAP_RESTRICTED_CHROOT" capability which allows chroot but only under given circumstances or a prctrl which "degrades" CAP_SYS_CHROOT to only work under given circumstances.
In both cases programs which drop all CAP's they don't need would not be affected by this feature made for programs which use chroot.
But in the current design the sandbox of ALL!!!! sandboxed programs which drop the CAP_SYS_CHROOT capability is weakened. Which IMHO is unreasonable.
What's the danger here, that a program will create a chroot and that an attacker will then break out of it? So we're back to where we are now, which is not using chroots.
Not quite right
Currently chroot needs privilegs, so a program which runs sandboxed will not ever be able to chroot and will be stuck in the sandbox.
But with that patch a sandboxed program could start a chroot and then use the chroot environment to weaken or escape the sandbox it is in.
So as far as I understand this change will actively weaken the security of all sandboxes which dropped the privilege to do chroot (or never had it), which are most of them.
The main way you could take advantage of it would be in combination with a RCE vulnerability in a software which runs itself in a sandbox.
> which is not using chroots.
Currently we can make sure chroot is not used by making sure no SYS_CAP_CHROOT or similar capability is given. With the patch it will be impossible to make sure chroot is not used!
Because anyone anywhere with anyuser will be able to use it.
Which would be fine with the constraints the patch adds to chroot, but the problem is that it's known that one of the main constraints it adds doesn't work perfectly/has security gaps.
> intentionally sacrifice security for usability.
The problem is that with the patch everyone using various non-vm sandboxing mechanisms will be forced to sacrifice security for usability, it's not a "opt-in for this programs which do care".
Which is why I think putting this behind another capability or similar would be best (one a unprivileged user can have).
chroot() is from ancient Unix/BSD times and was in Linux since pretty much the beginning of Linux.
Changing its behavior after the fact would break expected behavior of existing programs AND would break compatibility with other Unixen.
Back in high school (in Austria, speaking German) I've been told several times by a Unix grey beard I had as a teacher that "Unixen" is the preferred plural of Unix, similar to "VAXen" for VAX, which the English Wiktionary does seem to know about.
Even Unix v7 insists on chroot() being only called by the root user (the chroot syscall is in /usr/sys/sys/sys4.c).
I do see the usage for bootstrapping and troubleshooting so that does cause an issue.
Going out of compliance will come at some cost.
https://pubs.opengroup.org/onlinepubs/7908799/xsh/chroot.htm...
Linux systems adhere to POSIX,[81] SUS,[82] LSB, ISO, and ANSI standards where possible, although to date only one Linux distribution has been POSIX.1 certified, Linux-FT.[83][84]
https://en.wikipedia.org/wiki/Linux
Archive.org has the supporting documents.
https://web.archive.org/web/20160404122450/http://www.linuxj...
"Unifix GmbH (Braunschweig, Germany) developed a Linux system that has been certified to conform to FIPS 151-2 (a superset of POSIX.1). This technology was available in Unifix' own distribution called Unifix Linux 2.0 and in Lasermoon's Linux-FT."
https://web.archive.org/web/20111010111215/http://www.debian...
But I believe the appropriate solution would be either:
- a prctrl like PR_SET_RESTRICED_CHROOT which will "degrade" CAP_SYS_CHROOT to require all the thinks listed (but still requires CAP_SYS_CHROOT).
- a new capability like CAP_SYS_RESTRICTED_CHROOT (probably not an option).
The current patch would weakening the security sandbox of any process dropping CAP_SYS_CHROOT which IMHO is unacceptable given that PR_SET_NO_NEW_PRIVS is known as being imperfect.
unshare --map-current-user --root=<new root> <program>
And works completely unprivileged using namespaces.
Still, as namespaces gain more and more traction, the value of adding rootless chroot goes down.
In that case, it seems completely arbitrary to not make chroot work as a normal user then.
There are probably people today who run things in Docker containers as root who are thinking "OMG, this is a horrible idea!".
In the chroot environments I created at the time everything was statically linked and there was nothing else for the program(s) to run. Everything was audited. It didn't start with "it works on my machine, so why can't I ship my machine?" as a premise.
It is safe only insofar some other software with elevated privileges whose security model assumes that only root can chroot, not run.
This is an issue with security that is had to avoid; some software is written on the assumption that certain things are impossible that may become possible in the future.
It is also why most capabilities are in practice useless as a tool of granularity on the average system and that all capabilities can often be constructed from a subset that is often as large as a single one, as so much software was written and designed before such capabilities existed, under the assumption that, if one have one, one have all.
It's useful for other reasons. On OpenBSD, a full web browser compromise does not lead to full file system access.
I'm not sure what pieces of software populate directories and then chroot into them aside from maybe some build systems? But those likely create or bind in some /dev and /proc pieces which would be privileged operations anyway. And in such a case would containers not have surplanted chroot?
Chroot is itself sometimes used to provide container-style functionality, so I think it's wrong to say containers "surplanted" it.
Containers use chroot
For example, maybe you don't want the process to be able to easily detect that it has had its access reduced, by simulating a full-access environment.
Or for example, maybe you don't care about access at all and you just want to avoid conflicts between two processes by giving them separated namespaces for their data.