Дмитрий Столяров
v4
Проникновение в Docker
с примерами
Привет!
# whoami
dmitry.stolyarov
# hostname -d
flant.ru
# cat /etc/motd
Проникновение в Docker
с примерами
24×7×365 L1/L2/L3/L4 DevOps SLA
Опыт
Опыт
OpenSolaris Zones
Опыт
Gentoo и Linux-VServer 2006
OpenSolaris Zones
Опыт
Gentoo и Linux-VServer 2006
OpenSolaris Zones
procfs v1 by flant 2008
Опыт
Gentoo и Linux-VServer 2006
OpenSolaris Zones
procfs v1 by flant 2008
LXC
Опыт
Gentoo и Linux-VServer 2006
OpenSolaris Zones
procfs v1 by flant 2008
jailer by flant 2009
LXC
Опыт
Gentoo и Linux-VServer 2006
OpenSolaris Zones
procfs v1 by flant 2008
jailer by flant 2009
LXC
Docker 2013, осень
Опыт
Gentoo и Linux-VServer 2006
OpenSolaris Zones
procfs v1 by flant 2008
jailer by flant 2009
LXC
Docker 2013, осень
Docker 2014, 6 июня
Зачем проникать в Docker?
Continuous Delivery
Зачем проникать в Docker?
Тестовые окружения
Continuous Delivery
Зачем проникать в Docker?
Тестовые окружения
Continuous Delivery
Контейнеры
Зачем проникать в Docker?
Тестовые окружения
Continuous Delivery
Контейнеры
Зачем проникать в Docker?
}>90%
Тестовые окружения
Continuous Delivery
Контейнеры
}>90% Не нужен доступ
Зачем проникать в Docker?
Тестовые окружения
Continuous Delivery
Контейнеры Нужен доступ
}>90% Не нужен доступ
Зачем проникать в Docker?
OpenSSH OpenSSH
OpenSSH OpenSSH
:22 :22
OpenSSH OpenSSH
:22 :22
:23
OpenSSH OpenSSH
:22 :22
:23 :24
OpenSSH OpenSSH
:22 :22
reverse proxy
:22
Петя
OpenSSH
:22
Вася
Что такое Docker?
Что такое Docker?
capabilities
Что такое Docker?
capabilities
(2.2 / 1999)
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
cgroups
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
cgroups
(2.6.24 / Jan 2008)
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
cgroups
(2.6.24 / Jan 2008)
veth
(~ Sep 2007)
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
cgroups
(2.6.24 / Jan 2008)
veth
(~ Sep 2007)
aufs
(~ 2006)
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
cgroups
(2.6.24 / Jan 2008)
veth
(~ Sep 2007)
aufs
(~ 2006)
overlay
(3.18, Dec 2014)
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
cgroups
(2.6.24 / Jan 2008)
veth
(~ Sep 2007)
aufs
(~ 2006)
overlay
(3.18, Dec 2014)
kernel
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
cgroups
(2.6.24 / Jan 2008)
veth
(~ Sep 2007)
aufs
(~ 2006)
overlay
(3.18, Dec 2014)
Docker (~2014)
kernel
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
cgroups
(2.6.24 / Jan 2008)
veth
(~ Sep 2007)
aufs
(~ 2006)
overlay
(3.18, Dec 2014)
Docker (~2014)
kernel
unshare( );
unshare(CLONE_NEWIPC | CLONE_NEWNS |
CLONE_NEWNET | CLONE_NEWPID |
CLONE_NEWUTS);
unshare(CLONE_NEWIPC | CLONE_NEWNS |
CLONE_NEWNET | CLONE_NEWPID |
CLONE_NEWUTS);
if(fork()) {
wait(NULL);
return 0;
}
unshare(CLONE_NEWIPC | CLONE_NEWNS |
CLONE_NEWNET | CLONE_NEWPID |
CLONE_NEWUTS);
if(fork()) {
wait(NULL);
return 0;
}
umount("/proc");
mount("proc", "/proc", "proc", 0, 0);
unshare(CLONE_NEWIPC | CLONE_NEWNS |
CLONE_NEWNET | CLONE_NEWPID |
CLONE_NEWUTS);
if(fork()) {
wait(NULL);
return 0;
}
umount("/proc");
mount("proc", "/proc", "proc", 0, 0);
execl("/bin/bash", "/bin/bash", NULL);
#define _GNU_SOURCE
#include <sched.h>
#include <unistd.h>
#include <sys/mount.h>
#include <sys/wait.h>
int main() {
unshare(CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWNET | CLONE_NEWPID |
CLONE_NEWUTS);
if(fork()) {
wait(NULL);
return 0;
}
umount("/proc");
mount("proc", "/proc", "proc", 0, 0);
execl("/bin/bash", "/bin/bash", NULL);
}
# gcc unshare.c -o unshare
# gcc unshare.c -o unshare
# ./unshare
# gcc unshare.c -o unshare
# ./unshare
# ps ax
PID TTY STAT TIME COMMAND
1 pts/0 S 0:00 /bin/bash
12 pts/0 R+ 0:00 ps ax
# gcc unshare.c -o unshare
# ./unshare
# ps ax
PID TTY STAT TIME COMMAND
1 pts/0 S 0:00 /bin/bash
12 pts/0 R+ 0:00 ps ax
# netstat -natu
… nothing
#
pid
snprintf(pathbuf, 100, "/proc/%d/ns/net", pid);
snprintf(pathbuf, 100, "/proc/%d/ns/net", pid);
open(pathbuf, O_RDONLY)
snprintf(pathbuf, 100, "/proc/%d/ns/net", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/net", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/ipc", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/net", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/ipc", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/uts", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/net", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/ipc", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/uts", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/pid", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/net", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/ipc", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/uts", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/pid", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/mnt", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/net", pid);
setns(open(pathbuf, O_RDONLY), 0);
............
snprintf(pathbuf, 100, "/proc/%d/ns/mnt", pid);
setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/net", pid);
setns(open(pathbuf, O_RDONLY), 0);
............
snprintf(pathbuf, 100, "/proc/%d/ns/mnt", pid);
setns(open(pathbuf, O_RDONLY), 0);
if(fork()) {
wait(NULL);
return 0;
}
snprintf(pathbuf, 100, "/proc/%d/ns/net", pid);
setns(open(pathbuf, O_RDONLY), 0);
............
snprintf(pathbuf, 100, "/proc/%d/ns/mnt", pid);
setns(open(pathbuf, O_RDONLY), 0);
if(fork()) {
wait(NULL);
return 0;
}
execl("/bin/bash", "/bin/bash", NULL);
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
int main(int argc, char **argv) {
int pid = atoi(argv[1]);
char pathbuf[100];
snprintf(pathbuf, 100, "/proc/%d/ns/net", pid); setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/ipc", pid); setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/uts", pid); setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/pid", pid); setns(open(pathbuf, O_RDONLY), 0);
snprintf(pathbuf, 100, "/proc/%d/ns/mnt", pid); setns(open(pathbuf, O_RDONLY), 0);
if(fork()) {
wait(NULL);
return 0;
}
execl("/bin/bash", "/bin/bash", NULL);
}
# gcc setns.c -o setns
# gcc setns.c -o setns
# pstree -p $(pidof unshare)
unshare(5136)───bash(5137)
# gcc setns.c -o setns
# pstree -p $(pidof unshare)
unshare(5136)───bash(5137)
# ./setns 5137
# gcc setns.c -o setns
# pstree -p $(pidof unshare)
unshare(5136)───bash(5137)
# ./setns 5137
# ps ax
PID TTY STAT TIME COMMAND
1 pts/0 S+ 0:00 /bin/bash
42 pts/2 S 0:00 /bin/bash
52 pts/2 R+ 0:00 ps ax
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
cgroups
(2.6.24 / Jan 2008)
veth
(~ Sep 2007)
aufs
(~ 2006)
overlay
(3.18, Dec 2014)
Docker (~2014)
kernel
✔
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
cgroups
(2.6.24 / Jan 2008)
veth
(~ Sep 2007)
aufs
(~ 2006)
overlay
(3.18, Dec 2014)
Docker (~2014)
kernel
✔
# mkdir /sys/fs/cgroup/memory/mygroup
# mkdir /sys/fs/cgroup/memory/mygroup
# echo $$ > /sys/fs/cgroup/memory/mygroup/tasks
# mkdir /sys/fs/cgroup/memory/mygroup
# echo $$ > /sys/fs/cgroup/memory/mygroup/tasks
# cat /proc/$$/cgroup | grep memory
6:memory:/mygroup
# mkdir /sys/fs/cgroup/memory/mygroup
# echo $$ > /sys/fs/cgroup/memory/mygroup/tasks
# cat /proc/$$/cgroup | grep memory
6:memory:/mygroup
# bash
# mkdir /sys/fs/cgroup/memory/mygroup
# echo $$ > /sys/fs/cgroup/memory/mygroup/tasks
# cat /proc/$$/cgroup | grep memory
6:memory:/mygroup
# bash
# cat /sys/fs/cgroup/memory/mygroup/tasks
2165
4562
4572
# mkdir /sys/fs/cgroup/memory/mygroup
# echo $$ > /sys/fs/cgroup/memory/mygroup/tasks
# cat /proc/$$/cgroup | grep memory
6:memory:/mygroup
# bash
# cat /sys/fs/cgroup/memory/mygroup/tasks
2165
4562
4572
# echo $$ > /sys/fs/cgroup/memory/tasks
# rmdir /sys/fs/cgroup/memory/mygroup
# mkdir /sys/fs/cgroup/memory/mygroup
# echo $$ > /sys/fs/cgroup/memory/mygroup/tasks
# cat /proc/$$/cgroup | grep memory
6:memory:/mygroup
# bash
# cat /sys/fs/cgroup/memory/mygroup/tasks
2165
4562
4572
# echo $$ > /sys/fs/cgroup/memory/tasks
# rmdir /sys/fs/cgroup/memory/mygroup
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
cgroups
(2.6.24 / Jan 2008)
veth
(~ Sep 2007)
aufs
(~ 2006)
overlay
(3.18, Dec 2014)
Docker (~2014)
kernel
✔ ✔
Docker это rocket science?
Примочка непонятного действия?
Docker медленный для production?
Docker НЕ безопасный для production?
Что такое Docker?
capabilities
(2.2 / 1999)
namespaces
(2.6.19 / Nov 2006)
cgroups
(2.6.24 / Jan 2008)
veth
(~ Sep 2007)
aufs
(~ 2006)
overlay
(3.18, Dec 2014)
Docker (~2014)
kernel
Everything should be made
as simple as possible,
but not simpler.
Albert Einstein
Что нужно чтобы войти в Docker?
Что нужно чтобы войти в Docker?
Узнать pid и id контейнера
Что нужно чтобы войти в Docker?
Узнать pid и id контейнера
# docker inspect -f '{{.State.Pid}} {{.Id}}' container_name
Что нужно чтобы войти в Docker?
Добавить в cgroup`ы
Узнать pid и id контейнера
Что нужно чтобы войти в Docker?
Добавить в cgroup`ы
Узнать pid и id контейнера
for f in $(ls /sys/fs/cgroup/*/docker/$CONTAINER_ID/tasks)
do echo $$ > $f
done
Что нужно чтобы войти в Docker?
Добавить в cgroup`ы
Узнать pid и id контейнера
Сменить namepsace`ы
Что нужно чтобы войти в Docker?
Добавить в cgroup`ы
Узнать pid и id контейнера
Сменить namepsace`ы
Снять лишние capabilities
Петя
OpenSSH
:22
Вася
Петя
OpenSSH
:22
Вася
Петя
OpenSSH
:22
Вася
PAM
Петя
OpenSSH
:22
Вася
pam_docker
Петя
OpenSSH
:22
Вася
pam_docker
ProFTPd
:21
Петя
OpenSSH
:22
Вася
pam_docker
ProFTPd
:21
su / sudo
Петя
OpenSSH
:22
Вася
pam_docker
ProFTPd
:21
su / sudo
cron
php_fpm: master
php_fpm: master
W W W
php_fpm: master
W W W W W W
php_fpm: master
W W W W W W
Наши docker-проекты
github.com/flant/docker_penetration_experiment
github.com/flant/pam_docker
github.com/flant/php_fpm_docker
Дмитрий Столяров
dmitry.stolyarov@flant.ru
linkedin.com/in/distol
github.com/distol
Всем спасибо!
Тимофей Кириллов
github.com/distorhead

Docker penetration