ケイパビリティ
ケイパビリティとは
スーパーユーザー権限の細かい制御を提供することで, root ユーザーの使用を減らすことができる.
つまりrootか非rootかではなく, もっと細かい単位で権限を与えることが可能.
そのため, setuid属性を付与しなくてもケイパビリティで置き換えることが可能であり, 推奨されている.
実際にpingではCAP_NET_RAWが利用されており, 一般ユーザーでもpingを使うことができるようになっている.
$ getcap /bin/ping /bin/ping = cap_net_raw+ep
ケイパビリティの定義は/usr/include/linux/capability.h内でCAP_から始まるもので定義されている. いくつか抜粋すると以下のようなケイパビリティがある.
- CAP_CHOWN - ファイルのUIDとGIDを変更可能
- CAP_DAC_OVERRIDE - ファイルにアクセス(読み書き実行)可能
- CAP_DAC_READ_SEARCH - ファイルの読み出しと実行可能
- CAP_NET_BIND_SERVICE - 1024番未満のポートを使用可能
- CAP_NET_RAW - RAWソケットおよびPACKETソケットを使用可能
- CAP_SYS_CHROOT - chrootが可能
プロセスの持つケイパビリティを確認する
getpcapsコマンドの引数にプロセスIDを渡して実行する.
以下はhttpd(apache)のプロセスIDを引数として渡した例.
$ getpcaps 27252 Capabilities for `27252': = 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+ep
最後の+epはケイパビリティセットを表している.
プロセスはケイパビリティセットを持ち, 以下の3種類がある.
- effective - カーネルがスレッドの権限 (permission) をチェックするときに 使用するケーパビリティセット
- permitted - そのプロセスが持つことを許されているケイパビリティ
- inheritable - 実行時に継承されるケーパビリティセット
fork(2)で作成される子プロセスは, 親のケーパビリティセットのコピーを継承する.
また, capsetコマンドでプロセスは自分自身のケーパビリティセット を操作することができる.
例の場合, +epとあるのでeffectiveとpermittedがセットされている.
実行ファイルの持つケイパビリティを確認する
実行ファイルにケーパビリティセットを対応付けることができる.
- effective - これが設定されていなければ実行したときにプロセスのpermittedが設定されない
- permitted - 実行したときに許可されるケイパビリティセット
- inheritable - 実行時に継承されるケイパビリティセット
実行ファイルのケイパビリティセットを確認するにはgetcapコマンドを使用する.
$ getcap /bin/ping /bin/ping = cap_net_raw+ep
ケイパビリティをセットする
ここではpingコマンドにケイパビリティの付与, 削除を行ってみる.
$ cp /bin/ping /tmp/ping $ cd /tmp $ getcap ./ping
コピーしたpingにはケイパビリティは付与されていない. そのため, 一般ユーザーでは実行してもネットワークソケットを使えずにOperation not permittedと表示される.
$ ./ping 8.8.8.8 ping: icmp open socket: Operation not permitted
setcapコマンドを使って, ケイパビリティをセットする. ソケットを使用するため, CAP_NET_RAWにeffectiveとpermittedを設定する.
$ sudo setcap cap_net_raw=ep ./ping $ getcap ./ping ./ping = cap_net_raw+ep $ ./ping 8.8.8.8 -c 1 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=48 time=54.9 ms --- 8.8.8.8 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms
ケイパビリティの削除にはsetcapコマンドに-rオプションを渡す.
$ sudo setcap -r ./ping $ ./ping 8.8.8.8 ping: icmp open socket: Operation not permitted
これを使えば一般ユーザーでは参照できないディレクトリをlsコマンドで参照できるようになる.
man capabilities で調べるとCAP_DAC_READ_SEARCHの項目に
Bypass file read permission checks and directory read and execute permission checks;
とあるのでCAP_DAC_READ_SEARCHを付与すれば, ファイルの読み出し権限のチェックをバイパスできる.
実際にlsコマンドとcatコマンドに付与し, /root/hidden.txtを読み取ってみる.
$ cp /usr/bin/ls /tmp/ $ cp /usr/bin/cat /tmp/ $ cd /tmp $ ./ls /root ./ls: ディレクトリ /root を開くことが出来ません: 許可がありません $ sudo setcap cap_dac_read_search=ep ./ls $ ./ls /root hidden.txt $ ./cat /root/hidden.txt ./cat: /root/hidden.txt: 許可がありません $ sudo setcap cap_dac_read_search=ep ./cat $ ./cat /root/hidden.txt This file is root's file