ケーパビリティモードでのプログラミング
2016年7月15日
(株)創夢 内藤 祐一郎
ケーパビリティモード
● FreeBSD 9.0-R から された しいモード。搭載 新
● cap_enter(2) を び した の された 。呼 出 後 制限 環境
●
たなファイルディスクリプタを できなくなる。新 取得
● shmget(2) などのリソース ができなくなる。取得
●
ケーパビィティモードは プロセスにも される。子 継承
● cap_rights_limit(2) により かく細 (read, write, ...) できる制御
。
メリット
● selinux と なりユーザの が 。異 設定 不要
● root に setuid されたプログラムなど、
きすぎる を つプロセスが に を とせる。大 権限 持 自発的 権限 落
● えば例 ping, traceroute はパケット のために取得 root を権限
つため、 が が つかった に したパケットを持 万 一脆弱性 見 場合 細工
させるなどして の になりやすい。受信 攻撃 標的
●
ケーパビリティモードで していれば、 が されてもア動作 万 一攻撃
クセスできるリソースがないため を められる。安全性 高
● FreeBSD-11 から ping, traceroute はケーパビリティモードで
する。動作
なプログラムの れ基本的 流
1. 必要なファイルディスクリプタを取得する。
2. cap_enter(2) を実行する。
3. 必要があればさらに cap_rights_limit(2) で制限を加える。
4. アプリケーションとしての処理を実行する。
5. プロセス終了。
されるシステムコール制限
● chdir, stat, open, rename, mkdir, unlink など
にパス を るものは えない。引数 名 取 使
● connect, bind, sendto
に引数 struct sockaddr * をとり 、 を するも送信先 受信元 指定
の
● execve, wait, waitpid, wait3/4/6
● shm_open, shmget, msgget
● すると使用 ECAPMODE の errno が る。返
を けないシステムコール影響 受
● read, write, close, sendfile, select, poll, mmap など
のファイルディスクリプタを するもの既存 使用
● pipe, socket, accept, listen, kqueue など
のプロセスに するだけもの自分 影響
● getpid, getuid, time, gettimeofday など
なる のもの単 情報取得
● fork
より かい を える細 制限 加
● cap_rights_limit(2) によりファイルディスクリプタごとに細か
く制限することが可能。
➔ READ
➔ WRITE
➔ IOCTL
➔ FSTAT
➔ FUNLINK
➔ MMAP, MMAP_R, MMAP_W, MMAP_RW など
● 概ねファイルディスクリプタを操作するシステムコール毎に権限
を設定できる。
なファイルアクセス動的
● プログラム起動時に必要なリソースが全て判明しない場合はどう
するのか?
➔ アクセスする のディレクトリのファイルディスクリプタを してお予定 取得
き、 openat(2) でディレクトリ のファイルを く。以下 開
➔ または プロセスとの別 通信 (UNIX DOMAIN SOCKET) でオープンした
ファイルディスクリプタを け す。受 渡
となるシステムコール代替
● cap_enter(2) にディレクトリのファイルディスクリプタを前
open(" ディレクトリ名 ", O_RDONLY|O_DIRECTORY) で取得
しておく。
● openat, renameat, mkdirat など ~ at を する。系 使用
~ at は となるディレクトリのファイルディスクリプタ系 基準
から パスで する。相対 指定
● パスに相対 “ ..” を れて ディレクトリに がる はカーネル入 親 上 操作
に される。拒否
● fchdir, fstat などファイルディスクリプタを にとるものを引数
する。使用
プログラムの れ ファイルアクセス流 ( )
1. base=open(“/var/data”,O_RDONLY|O_DIRECTORY);
2. cap_enter();
3. fd=openat(base, “sample.txt”, O_RDWR);
4. read(fd, buf, size);
...
5. close(fd);
ネットワークの利用( UDP )
● cap_enter() の前にソケットを作成し、予め送信先や受信元を設
定しておく。
➔ sendto(2), bind(2) は えなくなる。使
● 送信先は connect(2) で指定する。
● 受信元は bind(2) で指定する。
プログラムの れ流 ( UDP 送信)
1. sock=socket(PF_UNSPEC, SOCK_DGRAM, 0);
2. < sockaddr に接続先を入れる >
3. connect(sock, &sockaddr, size);
4. cap_enter();
5. send(sock ,data, len);
6. recv(sock, buf, buf_len);
7. …
8. close(sock);
プログラムの れ流 ( UDP 受信)
1. sock=socket(PF_UNSPEC, SOCK_DGRAM, 0);
2. < sockaddr に受信元を入れる >
3. bind(sock, &sockaddr, size);
4. cap_enter();
5. recv(sock ,buf, buf_len);
6. send(sock, data, size);
7. …
8. close(sock);
ネットワークの利用( TCP )
● cap_enter() の にソケットを し前 作成 bind(2) または
connect(2) しておく。
● bind(2) のソケットに済 accept はできるため は 。受信 可能
● connect(2) はたとえ じ であっても できないため、同 接続先 使用
タイムアウトなどで することができない。再接続
●
クライアントプログラムならば、プロセスを する。再起動
● さもなければ unix domain socket を して、経由
プロセスが したソケットを け してもらう。別 接続 受 渡
ソケット け しの受 渡 例
親プロセス 子プロセス
socketpair(PF_UNIX)
fork()
send(“ ”ホスト名:ポート番号 )
connect()
sendmsg(ソケット)
recv()
recvmsg()
cap_enter()
プロセス生成
● fork, fexecve が えるため、使
ファイルディスクリプタさえあれば イメージを 。実行 起動可能
しかし、ケーパビリティモードは プロセスにも子
されるため、継承 /libexec/ld-elf.so.1 の み みに読 込
してしまう。失敗
スタティックリンクされたプログラムなら できる。起動
● wait ができないため、 ち わせる がない。待 合 手段
● 11-R では pdfork(2), pdwait(2) が される だったは実装 予定
ず。。。
その他
● libc を めたライブラリについては が い。含 制限 多
● fopen() ではなく fdopen() を うなど、プログラム での使 側 対処
が 。必要
● getpwent() など で にファイル内部 暗黙 (/etc/passwd など ) を
するものは えない。参照 使
● casperd を して なリソースにアクセスするようになる経由 必要
み。見込
に最後
root に setuid するプログラムを るときには作
ケーパビリティモードを すると使用
より なプログラムを ることができます。安全 作

Programming under capability mode

  • 1.
  • 2.
    ケーパビリティモード ● FreeBSD 9.0-Rから された しいモード。搭載 新 ● cap_enter(2) を び した の された 。呼 出 後 制限 環境 ● たなファイルディスクリプタを できなくなる。新 取得 ● shmget(2) などのリソース ができなくなる。取得 ● ケーパビィティモードは プロセスにも される。子 継承 ● cap_rights_limit(2) により かく細 (read, write, ...) できる制御 。
  • 3.
    メリット ● selinux となりユーザの が 。異 設定 不要 ● root に setuid されたプログラムなど、 きすぎる を つプロセスが に を とせる。大 権限 持 自発的 権限 落 ● えば例 ping, traceroute はパケット のために取得 root を権限 つため、 が が つかった に したパケットを持 万 一脆弱性 見 場合 細工 させるなどして の になりやすい。受信 攻撃 標的 ● ケーパビリティモードで していれば、 が されてもア動作 万 一攻撃 クセスできるリソースがないため を められる。安全性 高 ● FreeBSD-11 から ping, traceroute はケーパビリティモードで する。動作
  • 4.
    なプログラムの れ基本的 流 1.必要なファイルディスクリプタを取得する。 2. cap_enter(2) を実行する。 3. 必要があればさらに cap_rights_limit(2) で制限を加える。 4. アプリケーションとしての処理を実行する。 5. プロセス終了。
  • 5.
    されるシステムコール制限 ● chdir, stat,open, rename, mkdir, unlink など にパス を るものは えない。引数 名 取 使 ● connect, bind, sendto に引数 struct sockaddr * をとり 、 を するも送信先 受信元 指定 の ● execve, wait, waitpid, wait3/4/6 ● shm_open, shmget, msgget ● すると使用 ECAPMODE の errno が る。返
  • 6.
    を けないシステムコール影響 受 ●read, write, close, sendfile, select, poll, mmap など のファイルディスクリプタを するもの既存 使用 ● pipe, socket, accept, listen, kqueue など のプロセスに するだけもの自分 影響 ● getpid, getuid, time, gettimeofday など なる のもの単 情報取得 ● fork
  • 7.
    より かい をえる細 制限 加 ● cap_rights_limit(2) によりファイルディスクリプタごとに細か く制限することが可能。 ➔ READ ➔ WRITE ➔ IOCTL ➔ FSTAT ➔ FUNLINK ➔ MMAP, MMAP_R, MMAP_W, MMAP_RW など ● 概ねファイルディスクリプタを操作するシステムコール毎に権限 を設定できる。
  • 8.
    なファイルアクセス動的 ● プログラム起動時に必要なリソースが全て判明しない場合はどう するのか? ➔ アクセスするのディレクトリのファイルディスクリプタを してお予定 取得 き、 openat(2) でディレクトリ のファイルを く。以下 開 ➔ または プロセスとの別 通信 (UNIX DOMAIN SOCKET) でオープンした ファイルディスクリプタを け す。受 渡
  • 9.
    となるシステムコール代替 ● cap_enter(2) にディレクトリのファイルディスクリプタを前 open("ディレクトリ名 ", O_RDONLY|O_DIRECTORY) で取得 しておく。 ● openat, renameat, mkdirat など ~ at を する。系 使用 ~ at は となるディレクトリのファイルディスクリプタ系 基準 から パスで する。相対 指定 ● パスに相対 “ ..” を れて ディレクトリに がる はカーネル入 親 上 操作 に される。拒否 ● fchdir, fstat などファイルディスクリプタを にとるものを引数 する。使用
  • 10.
    プログラムの れ ファイルアクセス流( ) 1. base=open(“/var/data”,O_RDONLY|O_DIRECTORY); 2. cap_enter(); 3. fd=openat(base, “sample.txt”, O_RDWR); 4. read(fd, buf, size); ... 5. close(fd);
  • 11.
    ネットワークの利用( UDP ) ●cap_enter() の前にソケットを作成し、予め送信先や受信元を設 定しておく。 ➔ sendto(2), bind(2) は えなくなる。使 ● 送信先は connect(2) で指定する。 ● 受信元は bind(2) で指定する。
  • 12.
    プログラムの れ流 (UDP 送信) 1. sock=socket(PF_UNSPEC, SOCK_DGRAM, 0); 2. < sockaddr に接続先を入れる > 3. connect(sock, &sockaddr, size); 4. cap_enter(); 5. send(sock ,data, len); 6. recv(sock, buf, buf_len); 7. … 8. close(sock);
  • 13.
    プログラムの れ流 (UDP 受信) 1. sock=socket(PF_UNSPEC, SOCK_DGRAM, 0); 2. < sockaddr に受信元を入れる > 3. bind(sock, &sockaddr, size); 4. cap_enter(); 5. recv(sock ,buf, buf_len); 6. send(sock, data, size); 7. … 8. close(sock);
  • 14.
    ネットワークの利用( TCP ) ●cap_enter() の にソケットを し前 作成 bind(2) または connect(2) しておく。 ● bind(2) のソケットに済 accept はできるため は 。受信 可能 ● connect(2) はたとえ じ であっても できないため、同 接続先 使用 タイムアウトなどで することができない。再接続 ● クライアントプログラムならば、プロセスを する。再起動 ● さもなければ unix domain socket を して、経由 プロセスが したソケットを け してもらう。別 接続 受 渡
  • 15.
    ソケット け しの受渡 例 親プロセス 子プロセス socketpair(PF_UNIX) fork() send(“ ”ホスト名:ポート番号 ) connect() sendmsg(ソケット) recv() recvmsg() cap_enter()
  • 16.
    プロセス生成 ● fork, fexecveが えるため、使 ファイルディスクリプタさえあれば イメージを 。実行 起動可能 しかし、ケーパビリティモードは プロセスにも子 されるため、継承 /libexec/ld-elf.so.1 の み みに読 込 してしまう。失敗 スタティックリンクされたプログラムなら できる。起動 ● wait ができないため、 ち わせる がない。待 合 手段 ● 11-R では pdfork(2), pdwait(2) が される だったは実装 予定 ず。。。
  • 17.
    その他 ● libc をめたライブラリについては が い。含 制限 多 ● fopen() ではなく fdopen() を うなど、プログラム での使 側 対処 が 。必要 ● getpwent() など で にファイル内部 暗黙 (/etc/passwd など ) を するものは えない。参照 使 ● casperd を して なリソースにアクセスするようになる経由 必要 み。見込
  • 18.
    に最後 root に setuidするプログラムを るときには作 ケーパビリティモードを すると使用 より なプログラムを ることができます。安全 作