TheRemote/MinecraftBedrockServer

run inside chroot jail?

apiskors opened this issue · 8 comments

Hi, have you considered running Minecraft inside a chroot jail?
Or some other method to increase security, beyond the obvious part of running everything in its own "minecraft" Linux account?
I'm setting up a personal Minecraft Bedrock server right now, so I'd love to hear your thoughts on this...

Hello,

That's a great question! I think you are thinking about this the wrong way. If Docker is exploited they will take on the permissions of the Docker process. That is root.

Basically what you are asking is this: https://docs.docker.com/engine/security/rootless/

This doesn't have anything to do with the container though. It doesn't really matter what my user inside the container is. Let's say a hacker is skilled enough to have RCE on Minecraft Bedrock (there has never been one, ever). You're already dealing with one of the best hackers in the world at that point. They have 0 days for Minecraft Bedrock that have never been discovered and nobody knows they exist but they have them and they want YOUR server dead for some reason (even though the exploit itself is a 5-10K+ payday).

Now let's say they're attacking one of the containerized versions. They've now got access to the "root" user inside your container. Okay, now they need Docker exploits to jailbreak out into your main host OS. If they have these though you're screwed because you're running Docker as root, aren't you?

If you're concerned about this you would want to configure your Docker to not run as root. That's why I said I don't think you are thinking quite the right way about this. The container is being hosted by the Docker process with Docker's permissions. If it is exploited and your Docker is running is root then those are the permissions they will have.

The two exploits themselves would alone be worth thousands to tens of thousands of dollars. Each. It has never been done for Bedrock. Not once. It's extremely rare to be done with Docker itself but it has happened and is quickly patched. There is merit to what you are saying, but it is actually your Docker system configuration where this would be done.

The fake Docker user inside the container isn't the concern. It's your Docker daemon's permissions that are the threat and if Docker has exploits they will gain the rights of the Docker daemon. If they can exploit Docker then it doesn't matter what Docker's fake containerized user is. Just like when they exploit bedrock_server they would gain the permissions of the user running the host process.

Basically that is where you would want to secure! You are thinking about this the right way watching out for what has root permissions. The only tweak I would make to that is that it's the Docker process you need to secure from running as root. The container is Docker essentially if that makes sense and that is the process you would want to not be running as root. You can absolutely configure your Docker this way and it will secure all your containers like this!

In other words, if you don't want the Minecraft server running as root on Linux because if it's exploited they would have root access if that happened, you should think the same way about Docker. If they exploit the Docker process and it's running as root they would also have root access. The "root" user in the container itself is basically fake and it's all really just Docker. It's all ran and controlled by Docker and Docker's permissions. It only means anything if Docker says it does and if Docker is being exploited then that is exactly why this wouldn't make any difference.

That is where you have to stop it then. Docker shouldn't be running as root. The container is irrelevant as the container won't let them do any of this anyway so we're talking exploits/jailbreaks/etc against Docker itself which just like if the Minecraft server was running as root they would inherit root permissions from Docker if Docker is running as root and this is the problem you are trying to solve (and can with the link from earlier). Hopefully that helps!

James, AFAICT your default MinecraftBedrockServer script setup does not use use Docker at all, just traditional Unix/Linux stuff. Although I see now that you DO also offer a Docker containerized version. I wasn't planning on using Docker at all. My impression is that chroot is supposed to be simpler more efficient than Docker or other containers; but I lack experience with them. Are you recommending Docker INSTEAD of chroot?

Ugh! My bad. I thought this was the Bedrock container. Sorry about that! You're right for sure as for the past couple of days I had issues opened on the Bedrock container and assumed this was that (and it was the first thing I read this morning).

So this is absolutely possible. It would require creating an entire separate operating system on the disk for the chroot jail. It's essentially exactly the same as a Docker container to be honest. Docker also has an entire separate operating system / image installed that the chroot jail runs in.

These are tricky to set up and there are security issues with them if it isn't done exactly right. Here is how you would create a chroot with Ubuntu: https://packaging.ubuntu.com/html/chroots.html. You use debootstrap which will download and install a base copy of Ubuntu. This is basically a OS inside an OS (very similar to both virtualization and Docker).

Look at this step to see why this probably isn't a great approach:

$ sudo mount -t none -o bind /tmp trusty/tmp
$ xhost +
Some programs may need you to bind /dev or /proc.

You need to share your /tmp folder and potentially even the /bind and /proc folder and even /dev of the host OS with the container for this to work. That is not a good idea at all especially the proc and dev folder (you can access stuff you'd never be able to get to normally if you share these folders with the chroot which most people do). I am certain this would be less secure than using just the regular minecraft account approach and not having them in the sudoers group.

If the minecraft account is breached and it is not in the sudoers group and it doesn't have access to any files outside of it's home directory that is honestly ideal. It's like when people hack web servers and have access to the www-data user. If there isn't stuff to do inside the /var/www/html folder this is essentially worthless. It happens all the time and it's the first line of defense on Linux for sure (and very disappointing to attackers). This makes lateral movement extremely difficult or potentially impossible.

So to answer your question about whether I would use Docker over the standalone version for this specific reason my answer would probably be no. Running it as a non-privileged user will give you multiple layers of security that attackers are not going to bother defeating all of them. They will just move on to another target that is just running it as root rather than try to defeat your additional security that almost nobody else will even have on there (because this has never happened).

That's not to say it can't happen. It just happened on Java. It is a once every 5-10 year hack that happened on Java (and log4j was way bigger than Minecraft and was attacking things a lot more important through this exploit). If it did happen though unless you are being individually targeted (meaning you have an extremely popular server or extremely dangerous enemies) then it's simply not going to be worth it to continue attacking you vs. move to the next server on the list on Shodan/Censys.

I would always take Docker over the chroot jail though. Docker is basically a chroot jail with a lot more security and features added on top of it but it works essentially the same. It's actually even better because you can run the 64 bit container on ARM and other platforms and it functions essentially this way still. It's more contained than a chroot because while it does have to share some of these permissions behind the scenes you don't have to blanket mount your host OS's proc or dev folders or any of those for your applications to run.

Containerization is considered more secure across the board so if you have reason to believe you are going to be targeted beyond the norm of bots attacking servers with old exploits to see who hasn't patched / secured their setup then yes I would say this would be more secure than a chroot jail and if you don't run Docker as root it's an additional security layer / more secure than the standalone version as well. Docker has to share these same permissions too but there are a bunch of additional security layers for Docker introduced that won't exist on a normal chroot jail.

Sorry about confusing which project I'm in, although I'm glad we covered some of the Docker stuff because it did tie into this answer a little bit. I would say you will find Docker to be much simpler than setting up a chroot jail (check out the Ubuntu link above to see what I mean). It's basically a one liner to run the containerized version of it.

Thanks for asking this and sorry my answer was so long. You are not going to be the only one to ask this question and I'll probably have smoother answers for this later (or at least less verbose). It's always a challenging question how to secure these. In my opinion from the questions you are asking I think the Docker version not running as root will meet the security requirements you've outlined here and it should be a one-liner to set it up.

There are no hackers that can do this that are known to the world. Nobody has ever done this as far as anyone knows (except the hackers and they aren't talking if they have an exploit like this). It's still smart to think about this question because one day a vulnerability could drop and then you'll be ready. This project is many years old though and we have never seen a breach no matter how improperly people set up their server.

That is obviously not a guarantee it can't and won't happen as nobody can make that guarantee but I can tell you it hasn't ever happened so far on Bedrock ever (and it has on the Java version). It is unlikely if you are breached it will be through this. It's much more likely it will be through almost anything else (especially IoT and things with open ports that internally are running very outdated Linux distros and supporting utilities that often run web services).

If I were trying to attack someone with a Minecraft server I would actually just nmap scan their entire port range on their IP address and see what they have forwarded. Almost anything will be easier than trying to breach Bedrock which has no known public RCE exploits. I bet I can find some crappy webcam running an ancient Linux 3.X kernel though that I can find a breach for on Google and be in their network in seconds. I can almost always find something like this and people don't think about them at all.

You'd be surprised how much sleep people lose over securing their software but never install the firmware updates for their cameras and are often running 5-10 year old factory stock firmware. That's where I'm coming in then. If I was helping anyone secure their setup this is how I would start. Nmap everything they have open to the world. You could do something like a:

sudo nmap -v -sV -Pn -p 1-65500 --open --script=vulners X.X.X.X

This will tell you all internet facing services on an IP address and it will scan them for vulnerabilities automatically against the vulners database. This is how I and many other hackers would come in. If I was attacking you for your Minecraft server that's not where I would try to breach you. That's way too hard. You're almost certainly running something easier for me to get into that can be automatically found with vulners for example. The tool will link you directly to RCEs against vulnerable devices a lot of the time and when it can't you'll be aware they probably exist if you Google enough for them.

For what it's worth if you can't tell then yes I have experience with this. I can't imagine someone putting in the effort to get to the level where you can breach systems and want to attack Minecraft servers. It's so hard man to really do this stuff. When I've put effort into developing exploits (I have some unpublished ones in vendor disclosure) it has been toward cryptocurrency ASIC miners.

Why? Because they are machines that print money. There's no money in hacking Minecraft servers. It doesn't make sense for me to spend dozens to hundreds of hours trying to exploit them, nor would it to anyone who has gone down this road as you have countless opportunities available to make money to you both legally and illegally and you're one of the rare people with the knowledge to actually do it. That in and of itself is extremely valuable (too valuable to make sense for them to be doing this). It's always script kiddies running publicly released exploits you will encounter. Never someone like me unless you are big like if you run 2b2t or something (or if it's really personal targeting for some reason).

Hopefully that helps and let me know if I can clarify anything!

Right now, before I get to more complicated stuff like chroot or Docker, I'm working on just getting bedrock_server to run as its own "mc" Linux user. I'm surprised to see that your SetupMinecraft.sh script seems to assume that the user we want running bedrock_server, is the SAME as the user installing things by running SetupMinecraft.sh, who of course MUST have sudo! Am I overlooking some option to configure it to run as its own separate user?

So far I've made some obvious hacks to the "start.sh" and "/etc/systemd/system/mc-*.service" scripts to make them work when run with "sudo -u mc". Of course I hit file permission problems at first. But once I fixed those, and used netstat to find (and kill) the zombie process that was blocking port 19132, it seems to work, yay!

But it seems really weird that your SetupMinecraft.sh has all its other fancy features, but DOESN'T handle running as a separte user on its own. Which makes me think I might be missing something...

Btw, I'm told that people sometimes run dynamic websites and other complicated things inside chroots, so I don't see why running bedrock_server inside one would be any more difficult. "ldd bedrock_server | wc -l" says it depends on 13 shared libraries, while /bin/ls has 7. So that doesn't sound TOO bad... Sometime in the next couple weeks, I hope to experiment with using the Jailkit tools to set up a chroot for it. Maybe I'll eventually try Docker too.

Hey apiskors,

Ahh, yes, that is a sticking point for sure. This has come up a lot more on my blog than GitHub and I probably should add this to the documentation. It looks like setting up users for other types of services as well and is a very similar process..

sudo adduser minecraft
sudo mkdir /home/minecraft
sudo usermod -d /home/minecraft minecraft
sudo adduser minecraft sudoers

Now log in or change contexts to that new user and run SetupMinecraft.sh again followed by:

sudo deluser minecraft sudoers

That should be about it although you can go further and set the suid bits on a lot of your executables so that the minecraft user can't even run the utilities in /usr/bin. This is going very far but it will provide additional protection on a standalone version.

I think jailkit would be worth pursuing. These are chroot containers that handle a lot of the pitfalls I was talking about in my really, really long post. They will set up a lot of these mounts that have to be shared between the OS and the chroot container in a more secure way.

It's all way harder than docker though. A Docker container is literally a jail completely separated from the host OS (other than the few things we talked about). Using the Docker version would be 3 lines on any platform as well as any architecture (including on Raspberry Pi and ARM devices):

sudo apt install docker.io
sudo docker volume add myminecraft
docker run -it -v myminecraft:/minecraft -p 19132:19132/udp -p 19132:19132 -p 19133:19133/udp -p 19133:19133 05jchambers/legendary-bedrock-container:latest

and that's it. You now have a running Bedrock server in the background! It's jailed through Docker basically. The server files are available at:

/var/lib/docker/volumes/

and looks like this:

root@jamesgigabyte-linux:/var/lib/docker/volumes/minecraftbe/_data# ls
backups                       logs
bedrock_server                minecraftpe
bedrock_server_how_to.html    premium_cache
bedrock_server_symbols.debug  release-notes.txt
behavior_packs                resource_packs
Dedicated_Server.txt          server.properties
definitions                   structures
development_behavior_packs    treatments
development_resource_packs    valid_known_packs.json
development_skin_packs        worlds
downloads                     world_templates

Here you can see the docker volume's contents. When running Docker all of your persistent data has to be stored in that volume. If someone attacked it you would literally see the files they were writing to the disk in a theoretical attack. They're in a jailed volume.

They can't write to the base image (at least not persistently) and their changes would be lost upon restarting the container. The base image only exists in memory/cache, it's not real and it only loads that original base image each time the container starts. Basically in Docker the entire filesystem is also jailed to a Docker volume. Otherwise their changes wouldn't persist anywhere and couldn't without exploiting Docker itself.

Only the smartest attackers would even figure this out. Most of them would try to write changes to the base OS image not realizing it's fake and that nothing will persist when it's restarted. This is better than a chroot. In a chroot the files are real. They can be modified. Your chroot can be "infected" and this can't really happen with Docker base images. It could only happen with the volume and it would be difficult not to notice a bunch of weird stuff in there (nor would it have any impact on the host OS). The scripts also aren't stored in the volume which is a major bummer for attackers because that would be extremely easy remote code execution. It's just the minecraft server files though.

I cannot imagine you setting up a chroot jail with any alterative to Docker easier than this but it may be able to be just as easy (like maybe 2-3 steps?). I've heard of jailkit though before as well as some others. There is also systemd-nspawn which creates systemd capable containers. I've personally used systemd-nspawn to emulate systemd arm images on x86_64 using QEMU with these types of containers (very useful). If you try this definitely let me know if it ended up working pretty well / clean or if it ended up being clunkier. I honestly don't know.

The bedrock_server executable is a statically linked binary for the most part (you pointed out some of the links that it has) but mostly it's a big "blob" binary. That really helps, and it helped with developing the Docker container too for the same reason. I agree it doesn't sound too bad.

I would definitely really encourage you to try the Docker version though. I wouldn't push this as hard normally but it is exactly what you are trying to do and it works really well. I resisted all the calls in issues closed in here for me to finally make it for years. When I did finally do it I couldn't believe it. It really "just worked" even on Raspberry Pi which this exact script has a ton of code to try to make it work (very slowly) on the Pi. Everything is completely jailed off even the Docker volume.

I've never told anyone this but I honestly felt the exact same way you did about Docker. I figured I could just do it myself through configuration or something like a chroot way easier and it would work out the same or even better. The calls for me to make the Docker version go back further than that post I linked to even on my blog. I just didn't think it seemed necessary but it was really the log4j exploit that evolved my perspective on it a little bit here. The sticking points you will run into were all figured out on Docker years to a decade-ish ago. I'm very glad I finally did try it.

I'm not sure I'm ready to say (or accept) it's better than the standalone version but because of a lot of the issues that came up in this thread and how much better the Docker version would fare in these theoretical attacks I think it's safe to say I'm closer to acceptance of that and even see some security benefits I wasn't really thinking about before.

This is all theoretical. There has never been an attack like this. Again though I think it's worth investigating because a log4j-level-disaster exploit for Bedrock could drop someday. Anyone who says that is impossible I would definitely bet against on that one. It's just very hard and it's never happened yet but it's probably only a matter of time before something is found at some point.

I want to leave this issue open if you don't mind (unless you end up not checking out this) as I'm curious to see what you find with that experience. I definitely don't think everything works the best way it possibly could right now and am open to improvement. Maybe the SetupMinecraft.sh script should be changed to literally ask them for a user to set it up as.

Theoretically it could even set up the user for them although this makes me nervous across different distros but it could be done (even some of the commands I posted above are Ubuntu/Debianish commands and may not work on other distros where you'd want to use something like usermod -aG).

Closing for now but definitely let me know if you tried this / what the results were!

James, I never did try chroot, but I came up with some more restrictive SystemD security settings for Mojang's bedrock_server. You can find them here:

https://github.com/apiskors/saprolith/blob/master/systemd/mcb%40.service

Btw, thanks for the work you put into your MinecraftBedrockServer project, it was quite helpful in getting me started running my own Minecraft server!

Looks good, thank you for sharing!