Vault Policy の sudo について
Vault は path ベースでデータを管理しており、そのパスに対するアクセス管理は、ポリシーを定義することで実現します。
ポリシーは設定を誤るとより強力な権限を持ったポリシーを適用することができます。
ポリシーは、path に対して capability
と呼ばれる操作権限の可否を設定する必要があります。
今回は、capability の一つである sudo
に注目しました。
sudo
と聞くと、別のユーザや管理者権限で操作することを想起してしまいます。
Vault においては、特殊で create
, delete
などの capability
とは全く機能が異なります。
sudo
が付与されると、Root protected API にアクセスできるようになります。
Root protected API 自体も Path があるので、アクセスしたい API に応じて、Path に対する capability を設定する必要があります。
とはいえ、ドキュメントを見るだけでは、sudo
を使って何ができるのか、あまりイメージがわかなかったため、今回、sudo
でどんな悪用ができるのか色々試してみました。
検証環境の準備
今回は Minikube を使い公式 Helm Chart にて検証環境を作っています。
手順は https://developer.hashicorp.com/vault/tutorials/kubernetes/kubernetes-minikube-consul です。
Unseal まで実施し、Pod vault-0
に exec /bin/sh
までしてください。
User Bob と Alice を追加
最初は Root Token しかいないので、Bob と Alice のポリシー、ユーザを Root 権限で追加してください。
$ vault login
Token (will be hidden):
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token <SECRET>
token_accessor AZSutG9aeFNmmW8haVLCGOvj
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
$ vault policy write bob bob.hcl
$ vault policy write alice alice.hcl
$ vault write auth/userpass/users/bob password=password policiy=bob
$ vault write auth/userpass/users/alice password=password policiy=alice
今回は userpass
で認証します。
$ vault auth enable userpass
User Bob と Alice には、それぞれ以下のようなポリシーを用意し、ユーザとして追加します。
Bob と Alice は自分に割り当てられた Secret しかアクセスできないという設定です。
path "secret/data/bob/*" {
capabilities = ["create", "read", "delete", "update", "patch", "list"]
}
path "secret/data/alice/*" {
capabilities = ["create", "read", "delete", "update", "patch", "list"]
}
各ポリシーを Vault に登録します。
$ vault policy write bob bob.hcl
Success! Uploaded policy: bob
$ vault policy write alice alice.hcl
Success! Uploaded policy: alice
Bob と Alice をそれぞれのポリシーで追加します。
$ vault write auth/userpass/users//bob password=password policies=bob
Success! Data written to: auth/userpass/users//bob
$ vault write auth/userpass/users//alice password=password policies=alice
Success! Data written to: auth/userpass/users//alice
$ vault kv put secret/bob/foo name=bob
$ vault kv put secret/alice/foo name=alice
Bob でログインできるか試します。
$ vault login -method=userpass username=bob
Password (will be hidden):
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token <SECRET>
token_accessor JIIYb9PmF7QuUtqaxwWQqFb8
token_duration 768h
token_renewable true
token_policies ["bob" "default"]
identity_policies []
policies ["bob" "default"]
token_meta_username bob
Bob の Policy は default と bob になっています。
Bob は bob ポリシーが適用されており、自分の Secret は読み書きできますが、Alice の Secret には何も操作できません。
以下のコマンドで確認します。
$ vault kv put secret/bob/foo name=bob
=== Secret Path ===
secret/data/bob/foo
======= Metadata =======
Key Value
--- -----
created_time 2022-12-05T04:43:26.754224183Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 2
$ vault kv get secret/alice/foo
Error reading secret/data/alice/foo: Error making API request.
URL: GET http://127.0.0.1:8200/v1/secret/data/alice/foo
Code: 403. Errors:
* 1 error occurred:
* permission denied
$ vault kv put secret/alice/foo name=bob
Error writing data to secret/data/alice/foo: Error making API request.
URL: PUT http://127.0.0.1:8200/v1/secret/data/alice/foo
Code: 403. Errors:
* 1 error occurred:
* permission denied
sudo 権限付与によって、任意のポリシーの Token を作る
Bob があるアプリケーションを構築しており、token を自由に払い出し、そのアプリケーションが Vault にアクセスする形にしたい、と Vault の管理者に要望を出しました。
管理者は良かれと思い、Bob に、Token 作成に必要な以下の Policy を追加しました。
path "auth/token/*" {
capabilities = ["create", "update", "sudo"]
}
$ vault policy write token token.hcl
Success! Uploaded policy: token
$ vault write auth/userpass/users/bob password=password policies=bob policies=token
Success! Data written to: auth/userpass/users/bob
これで Bob は自由に Token が作成できます。が、これは結構まずい状況です。
早速 Bob の権限で Alice の権限に昇格してみます。
Bob は自身のポリシーでは、Alice のポリシーを見る・知ることはできませんが、ポリシー名さえわかれば Alice に適用されているポリシーを持つ Token を作成できます。
$ vault login -method=userpass username=bob
$ vault policy list
Error listing policies: Error making API request.
URL: GET http://127.0.0.1:8200/v1/sys/policies/acl?list=true
Code: 403. Errors:
* 1 error occurred:
* permission denied
$ vault token create -policy=alice
...
token <TOKEN>
$ vault login <TOKEN>
$ vault kv put secret/alice/foo name=bob
==== Secret Path ====
secret/data/alice/foo
======= Metadata =======
Key Value
--- -----
created_time 2022-12-05T05:09:53.927799246Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 2
$ vault kv get secret/alice/foo
==== Secret Path ====
secret/data/alice/foo
======= Metadata =======
Key Value
--- -----
created_time 2022-12-05T05:09:53.927799246Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 2
==== Data ====
Key Value
--- -----
name alice
Alice の Secret 領域に読み書きができました。
Vault 管理者はどうすればよかったのか?
今回、Vault の管理者が Token 発行権限を Bob に与えたことが致命的でした。
任意の Policy を設定できてしまう Token 発行は必ず Vault の管理者が管理しましょう。
任意の認証手段の有効化と組み合わせ、任意のポリシーを付与する
あるシステムが Vault の認証に使えるということに Bob は気づきました。
Bob は検証のため、Vault の認証機能の有効無効を自由に変更したいと Vault の管理者に要望を出しました。
管理者は良かれと思い、Bob に以下のポリシーを追加してあげました。
その際、管理者は、有効無効を管理できるよう sys/auth
の権限と、auth/bob
以下のパスを Bob 専用の認証情報専用に付与したと、Bob に伝えました。
path "auth/bob/*" {
capabilities = ["create"]
}
path "sys/auth/*" {
capabilities = ["create", "update", "read", "sudo"]
}
$ vault policy write auth auth.hcl
Success! Uploaded policy: auth
$ vault write auth/userpass/users/bob password=password policies=bob policies=auth
Success! Data written to: auth/userpass/users/bob
Bob は任意の認証設定を Vault に追加し、Token 作成時と同様に、Alice のポリシーを持ったユーザを作成できます。
ここでは Bob 専用に割り当てられた path で管理される userpass を追加しています。
$ vault login -method=userpass username=bob
$ vault auth enable -path=bob/userpass userpass
Success! Enabled userpass auth method at: bob/userpass/
$ vault write auth/bob/userpass/users/fake-alice password=password policies=alice
Success! Data written to: auth/bob/userpass/users/fake-alice
$ vault login -method=userpass -path=bob/userpass username=fake-alice
Password (will be hidden):
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token <SECRET>
token_accessor 7CiDeWp2XqvoiGyLBzfQpsRc
token_duration 768h
token_renewable true
token_policies ["alice" "default"]
identity_policies []
policies ["alice" "default"]
token_meta_username fake-alice
Vault 管理者はどうすればよかったのか?
今回、Vault の管理者が権限を auth
以下と sys/auth
以下に与えたのがよくありませんでした。
sys/auth
に対して、本当に sudo
が必要だったのでしょうか。Vault の認証方法は管理者が管理すべきではないでしょうか。
また、auth/bob
に関しても、Bob に一任するのが適切だったのでしょうか?認証情報は管理者が管理するよう、create
は提供せず、Bob は一覧表示できる程度でも良かったのではないでしょうか。
まとめ
今回は sudo
でどういったことができるかという実験をしました。結果として、ユーザが任意のポリシーの Token 作成, ユーザ追加をすることができました。
文中では、Alice というユーザの権限への昇格をしましたが、ポリシーはユーザの他に組織やシステム単位で設定されるのが一般的ですので、より大きな権限が付与されうることを意味します。
また、sudo
を利用することで、今回検証していない API に対してもアクセスができます。
例えば、pki/root
に sudo
を付与することで PKI の秘密鍵を削除し、Vault PKI を使っているシステムに不具合を発生させたり、sys/audit/:path
に sudo
を付与することで監査を削除したり、都合のよいものにすり替えることもできそうです。
Vault の管理をされる方は、ユーザに sudo
を設定しないことを基本とした上で、本当に必要かどうか考えるのがよいと思います。
余談
実は、本調査の前に社内で sudo
が設定されているポリシーが事例が散見されました。
Issue や PR を見ても、なぜ sudo
が追加されているのかわかりませんでした。
そもそも私も sudo
の影響がわからないということもあったので、今回、影響調査を実施してみました。
本記事によってなんとなく付けている sudo
設定が減ったら幸いです。