はじめに
本記事はLinuxのcapabilityについて記載しています。
capabilityを翻訳すると、能力や、機能を意味します。
ビジネスの世界でもケイパビリティという言葉は使用されていますが、Linuxの世界でもcapabilityという言葉が存在します。
Linuxのcapability
前提としてLinux上のファイルなどオブジェクトに対するアクセス制御は、一般的には以下の2種類があります。
- 任意アクセス制御(DAC:Discretionary Access Control)
- ファイルパーミッションを基本とし、オブジェクトのアクセス権を所有者、グループ、その他に分類してアクセス可能なユーザーを制限
- アクセス制御リスト(ACL:Access Control List)を用いて、特定のユーザーやグループなどに対するACLを設定
- 強制アクセス制御(MAC:Mandatory Access Control)
- 任意アクセス制御より細かなアクセス制御設定が可能
- SELinux/AppArmor/SmackなどセキュアOSで実現
Linuxのcapabilityは、ファイルやプロセスなどのリソースに対して付与される権限の組み合わせを指します。
従来のUNIX実装では、パーミッションチェックを実行するために、特権プロセス(実効ユーザーIDが0)と、非特権プロセス(実効UIDが0以外)に大別できます。特権プロセスはすべてのカーネル許可チェックをバイパスしますが、非特権プロセスはプロセスの資格情報に基づいて認可を受けます。
Linux2.2以降、Linuxは従来スーパーユーザーに関連付けられていた特権を、機能と呼ばれる個別の単位に分割し、個別に有効化および無効化できます。機能はスレッドごとの属性です。
ファイル機能により、ユーザーはより高い権限でプログラムを実行できます。これは、ビットの動作に似ています。スレッド機能は、実行中のプログラム機能の現在の状態を追跡します。
従ってcapabilityを使用することで、rootユーザーを使用することなく、RAWソケットを使用するなどの特権操作が実行できます。
強制アクセス制御を実現するSELinuxは、米国国家安全保障局 (National Security Agency)によって開発されています。
getcap
getcapコマンドは、指定された各ファイルの名前とcapabilityを表示します。
-r
オプションを付与することで、再起的な検索もできます。
getcap
コマンドの使用例について以下に記載します。
- ファイルのcapabilityを表示
$ getcap /usr/bin/ping
/usr/bin/ping cap_net_raw=ep
- システム全体のcapabilityを表示
$ getcap -r / 2> /dev/null
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper cap_net_bind_service,cap_net_admin=ep
/usr/bin/dumpcap cap_net_admin,cap_net_raw=eip
/usr/bin/fping cap_net_raw=ep
/usr/bin/ping cap_net_raw=ep
上記出力結果を踏まえて、/usr/bin/pingファイルにcap_net_rawというcapabilityが設定されているのが分かります。pingコマンドはRAWソケットとPACKETソケットを使用しています。capabilityという仕組みを用いて、必要な権限だけを与えています。
capsh
capshコマンドは、Linuxのcapability管理ができるコマンドです。
オプションの注意点としては、指定された順序で作用します。
- 現在のcapabilityの状態を表示
$ capsh --print
capshコマンドを使用して、スーパーユーザーなどrootユーザーに対する制限も可能です。
コンテナのcapability
コンテナでもcapabilityを設定することができます。
Kubernetesの公式ドキュメント1より、Set capabilities for a Containerを参考にしながら試してみましょう。
以下2つのPodをデプロイします。
- pods/security/security-context-3.yaml
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-3
spec:
containers:
- name: sec-ctx-3
image: gcr.io/google-samples/node-hello:1.0
- pods/security/security-context-4.yaml
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-4
spec:
containers:
- name: sec-ctx-4
image: gcr.io/google-samples/node-hello:1.0
securityContext:
capabilities:
add: ["NET_ADMIN", "SYS_TIME"]
デプロイしたPodのコンテナにログインを行い、capsh --print
コマンドを実行します。
- security-context-demo-3
Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+eip
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
Securebits: 00/0x0/1'b0
secure-noroot: no (unlocked)
secure-no-suid-fixup: no (unlocked)
secure-keep-caps: no (unlocked)
uid=0(root)
gid=0(root)
groups=
- security-context-demo-4
Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_admin,cap_net_raw,cap_sys_chroot,cap_sys_time,cap_mknod,cap_audit_write,cap_setfcap+eip
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_admin,cap_net_raw,cap_sys_chroot,cap_sys_time,cap_mknod,cap_audit_write,cap_setfcap
Securebits: 00/0x0/1'b0
secure-noroot: no (unlocked)
secure-no-suid-fixup: no (unlocked)
secure-keep-caps: no (unlocked)
uid=0(root)
gid=0(root)
groups=
上記出力結果の通りに、security-context-demo-4のコンテナに対して、CAP_NET_ADMIN
と、CAP_SYS_TIME
が設定されているのが分かります。
付与されるcapabilityの範囲が異なるため、capabilityによって細分化されたプロセスの特権(root権限)が付与されたことが分かります。
また、Dockerでもdocker run
コマンドを用いてcapabilityを設定することができます。
おわりに
Linuxのセキュリティに興味がある場合は、LPIC303の受験がお奨めです。
LPIC303では、強制アクセス制御などの仕組みについて学ぶことができます。
また、LPIC3については重要なお知らせの通りに、2022年でVersion2.0が廃止され、現在はVersion3.0に更新されているため、受験する際はご注意ください。
参考
-
Kubernetes Documentation. Configure a Security Context for a Pod or Container ↩