-
Notifications
You must be signed in to change notification settings - Fork 1
Hardening SEGFAULT
Already one important and deeply implemented core concept of containers and docker, the following mechanisms are widely adopted.
Cgroups involve resource metering and limiting:
- memory
- CPU
- block I/O
- network
Provide process isolation, complete isolation of containers, separate file system. There are 6 types of namespaces:
- mount ns - for file system.
- UTS(Unique time sharing) ns- which checks for different hostnames of running containers
- IPC ns - interprocess communication
- Network ns- takes care of different ip allocation to different containers
- PID ns - process id isolation
- user ns- different username(uid)
When going mainly public mid octover, it occured that there were quite some cases of resource exhaustion and denial of service, which is why it seems that more limits are needed to ensure users cannot wreak that big amount of havoc.
- Some ppl simply build forkbombs
- another was able to fill up HD space by increasing /etc/hosts up to 20GB - that file is treated special by docker and by default does not receive the restrictions which are set on the fs itself:
cat /dev/urandom >>/etc/hosts
This could be addressed via a
--storage_opt size=100m
option (found via @deadpackets here)
Note: This requires the overlay over xfs using the 'pquota' mount options. but /etc/hosts is treated special within docker.
Another hacker just created billions of 1B sized files so that the whole kernel just crashed xD
General search results here.
This could be implemented either on the docker daemon/process itself or deployed in the instance (or both), more information here. The basic idea is to restrict a processes access to files and capabilities. Docker can be started using such a profile via
$ docker run --rm -it --security-opt apparmor=your_profile hello-world
A docker default profile is available here or here, a comparison of apparmor vs. seccomp vs. capabilities can be found here.
We entered a simple search and found quite some options there:
In /etc/default/grub, set
GRUB_CMDLINE_LINUX="cdgroup_enable=memory swapaccount=1"
then
sudo update-grub
sudo docker run -it --memory="1g" ubuntu
sudo docker run -it --memory="1g" --memory-swap="2g" ubuntu
sudo docker run -it --memory="1g" --memory-reservation="750m" ubuntu
sudo docker run -it --cpus="1.0" ubuntu sudo docker run -it --cpus-shares="700" ubuntu
Info from here:
sudo docker run -it --pids-limit 32 ...
- Create a file to /etc/systemd/system/docker_limit.slice
[Slice] CPUAccounting=true CPUQuota=700% #Memory Management MemoryAccounting=true MemoryLimit=25G
- Start unit: systemctl start docker_limit.slice
- Edit /etc/docker/daemon.json
{ "cgroup-parent": "/docker_limit.slice" }
- Restart Docker daemon: systemctl restart docker
- In order to verify all works as expected: systemd-cgtop, you should see processes listed under docker_limit.slice
Taken from here, we can set it in the config or use it at the commandline:
docker run --ulimit nofile=<softlimit>:<hardlimit>
Found by @deadpackets via here:
--storage_opt size=100m
which is supported only for overlay over xfs with 'pquota' mount option.
Same approach, more info available here.
This can be set permanent via /etc/security/limits.conf. If we run it on a current system, it gives us:
┌──(root💀sf-TipSock)-[/root] └─# ulimit -a -t: cpu time (seconds) unlimited -f: file size (blocks) unlimited -d: data seg size (kbytes) unlimited -s: stack size (kbytes) 8192 -c: core file size (blocks) unlimited -m: resident set size (kbytes) unlimited -u: processes unlimited -n: file descriptors 256 -l: locked-in-memory size (kbytes) 64 -v: address space (kbytes) unlimited -x: file locks unlimited -i: pending signals 15450 -q: bytes in POSIX msg queues 819200 -e: max nice 0 -r: max rt priority 0 -N 15: rt cpu time (microseconds) unlimited
To achieve this to prevent fork bombs, we can first set it to a reasonable number:
ulimit -u 10 -u: processes 10
and then try to fork bomb:
:(){ :|:& };:
which unhappily still works - we can still relogin, and we had to type halt in the end to kill it xD
ulimit -f 50
ulimit -v 1000
ulimit -n
There are plenty of mechanisms to control the amount of packets using netfilter extensions like connlimit, limit or hashlimit. Depending on what to regulate, these filtering rules should be placed in the filter (for input and forward) or the mangle (additionally for prerouting and postrouting) table.
This targets port 80:
iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j DROP
This targets SYN-Packets:
iptables -N synflood iptables -A synflood -m limit --limit 10/second --limit-burst 24 -j RETURN iptables -A synflood -j REJECT iptables -A INPUT -p tcp --syn -j synflood
iptables -N syn-flood iptables -A INPUT -p tcp --syn -j syn-flood iptables -A syn-flood -p tcp --syn -m hashlimit --hashlimit 200/sec --hashlimit-burst 3 --hashlimit-htable-expire \ 300000 --hashlimit-mode srcip --hashlimit-name testlimit -j RETURN iptables -A syn-flood -m recent --name blacklist --set -j DROP iptables -A INPUT -j syn-flood
Join us on Telegram.