前回はプロセスに設定されているケーパビリティと,
今回はまず,execve(2)
システムコールを使ってプログラムを実行する際にケーパビリティがどのように変化するのかを説明したあと,
プログラム実行時のケーパビリティ
Linux上で実行されるプログラムは,fork(2)
やclone(2)
システムコールを使って親プロセスを複製して生成し,execve(2)
システムコールで目的のプログラムを実行します。
このexecve(2)
でプログラムを実行する際に,
P'(ambient) = (file is privileged) ? 0 : P(ambient) ...(1)
P'(permitted) = (P(inheritable) & F(inheritable)) |
(F(permitted) & P(bounding)) | P'(ambient) ...(2)
P'(effective) = F(effective) ? P'(permitted) : P'(ambient) ...(3)
P'(inheritable) = P(inheritable)
P'(bounding) = P(bounding)
ここで,
P()
: execve(2)
前のスレッドのケーパビリティセット
P'()
: execve(2)
後のスレッドのケーパビリティセット
F()
: ファイルケーパビリティセット
を示します。
execve後のケーパビリティの計算とファイルケーパビリティ
ここで一番複雑に見えるのは式
式(1)
式(2)P(inheritable) & F(inheritable)
",F(permitted) & P(bounding)
",P'(ambient)
はORですので,execve(2)
後のPermittedケーパビリティで許可されます。
AmbientP'(ambient)
)
ファイルケーパビリティで設定できるそれぞれのケーパビリティセットを紹介しながら,
- Permitted
- ここで許可したケーパビリティは,
Inheritableケーパビリティでの許可の有無に関わず execve(2)
後のPermittedケーパビリティ( P'(permitted)
)で許可されます。ただし, バウンディングセット ( P(bounding)
)で許可されている場合のみです。あとでバウンディングセットの部分で詳しく説明します - Inheritable
- ここで許可したケーパビリティは,
プロセスの execve(2)
前のInheritableケーパビリティ( P(inheritable)
)で許可されていれば, execve(2)
後のPermittedケーパビリティ( P'(permitted)
)で許可されます - Effective
- ファイルケーパビリティのEffectiveケーパビリティは,
他のふたつと違って0 or 1の単一の値です
式(3)
- 設定されている場合
- アルゴリズムで計算した
execve(2)
後のPermittedケーパビリティ( P'(permitted)
)の値が execve(2)
後のEffectiveケーパビリティ( P'(effective)
)に設定されます - 設定されていない場合
execve(2)
後のAmbientケーパビリティの値( P'(ambient)
)が execve(2)
後のEffectiveケーパビリティ( P'(effective)
)に設定されます
Ambientケーパビリティ
ここまで説明したファイルケーパビリティを使えば,ping
コマンドのように,
ところがファイルケーパビリティはファイルに属性を持たせますので,
セキュリティ的に必要な特権を与える範囲を最小限に限定したいという場合,
親プロセスが持っているケーパビリティの一部だけを継承し,
このような場合に使うのがAmbientケーパビリティです。このAmbientケーパビリティは比較的新しい機能で,
この機能が追加されるまで,
P'(permitted) = (P(inheritable) & F(inheritable)) |
(F(permitted) & cap_bset)
P'(effective) = F(effective) ? P'(permitted) : 0
P'(inheritable) = P(inheritable)
(cap_bsetはバウンディングセット)
このアルゴリズムでもInheritableケーパビリティがありますので,
なぜなら,execve(2)
で生成したプロセスにケーパビリティを与えるには,P'(permitted)
で目的のケーパビリティセットを有効にできません。その結果,P'(effective)
でもケーパビリティを有効にできません。
ファイルケーパビリティを設定してしまえば,
そこで登場したのがAmbientケーパビリティです。Ambientケーパビリティは特権を持たないプロセスのexecve(2)
の前後で継承されるケーパビリティです。
Ambientケーパビリティは,
また,
そして,setuid
,setgid
,
そして
先に書いたような目的の場合に,
Ambientケーパビリティは説明だけでも比較的わかりやすい機能かもしれませんが,
前回の実行例のように,setuid
も設定されていないping
コマンドをAmbientケーパビリティを使って実行してみましょう。
UbuntuやCentOS 8でインストールされるlibcap 2.
$ cp /bin/ping . (コピーしたのでファイルケーパビリティは外れる) $ /sbin/getcap ./ping (ファイルケーパビリティは設定されていない) $ sudo capsh --caps="cap_setpcap,cap_setuid,cap_setgid+ep cap_net_raw+ip" \ (1) > --keep=1 \ (2) > --uid=1000 \ (3) > --addamb="cap_net_raw" \ (4) > --print \ (5) > -- -c "./ping -c 1 127.0.0.1" Current: = cap_net_raw+ip cap_setgid,cap_setuid,cap_setpcap+p (1で指定したケーパビリティが設定されている) Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read Ambient set =cap_net_raw (Ambientケーパビリティが設定されている) Securebits: 020/0x10/5'b10000 secure-noroot: no (unlocked) secure-no-suid-fixup: no (unlocked) secure-keep-caps: yes (unlocked) (--keepオプションを指定したのでyesになっている) secure-no-ambient-raise: no (unlocked) uid=1000(karma) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),5(tty),6(disk),10(wheel),11(floppy) PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.023 ms --- 127.0.0.1 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.023/0.023/0.023/0.000 ms (pingコマンドが実行できた)
引数も実行結果も長いのでかえってわかりづらいかもしれませんね(^^)。何をやっているのかを簡単に説明しましょう。capsh
コマンドは指定した順でオプションが処理されますので,
オプションを与えた順に処理されますので,
- Ambientケーパビリティを設定するために
cap_
を親プロセスsetpcap ( capsh
コマンド)に設定 (このケーパビリティがないとIhneritableにケーパビリティを設定できません) - uid=1000でコマンドを実行するために
cap_
を親プロセスに設定setuid,cap_ setgid - Permitted,
InheritableケーパビリティがないとAmbientに設定できないので cap_
を親プロセスに設定net_ raw
--keep=1
はあとで説明するsecurebitsフラグを設定(このフラグを設定する際にも cap_
が必要)setpcap - 一般ユーザ権限で実行するために
--uid=1000
を指定 --addamb=cap_
でnet_ raw ping
コマンドの実行に必要なcap_
をAmbientケーパビリティに設定net_ raw - capsh実行時の状態を確認するために
--print
オプションを指定
Current
行でオプションで設定したケーパビリティが設定されていること,Ambient set
行でcap_
が設定されていることが確認できます。
Ambientケーパビリティを設定したので,ping
コマンドが実行できています。