Debian Gnu/Linuxで機能を実験しています。
/ bin/pingを現在の作業ディレクトリにコピーしました。期待どおりに機能しません。元々はsetuid rootでした。
次に、Sudo /sbin/setcap cap_net_raw=ep ./ping
を実行して、pingに最小限の機能(ルートではない)を与えます。pingは期待どおりに機能します。
次に、Sudo /sbin/setcap -r ./ping
を使用してその機能を取り消します。現在、期待どおりに動作していません。
capsh
を使用してpingを機能させるようにします。
capsh
には特権がないため、rootとして実行する必要がありますが、その後、rootをドロップして、他のすべての特権を削除します。
私はsecure-keep-caps
も必要だと思います。これはcapsh
に記載されていませんが、機能マニュアルに記載されています。 /usr/include/linux/securebits.h
からビット番号を取得しました。 --print
の出力はこれらのビットが正しいことを示しているため、これらは正しいように見えます。
私は何時間もいじっていますが、今のところこれを持っています。
Sudo /sbin/capsh --keep=1 --secbits=0x10 --caps="cap_net_raw+epi" == --secbits=0x10 --user=${USER} --print -- -c "./ping localhost"
ただし、ping
エラーはping: icmp open socket: Operation not permitted
で発生しますが、これは、機能がない場合に発生します。また、--print
はCurrent: =p cap_net_raw+i
を示していますが、これではe
が十分ではありません。
Sudo /sbin/capsh --caps="cap_net_raw+epi" --print -- -c "./ping localhost"
は機能をCurrent: = cap_net_raw+eip
に設定します。これは正しいですが、root
のままにします。
Sudo /sbin/capsh --keep=1 --secbits=0x11 --caps=cap_net_raw+epi --print -- -c "touch zz; ./ping -c1 localhost;"
を試しました
これにより以下が生成されます:
touch: cannot touch `zz': Permission denied
ping: icmp open socket: Operation not permitted
最初のエラーはsecure-noroot: yes
として予期されますが、2番目のエラーはCurrent: = cap_net_raw+eip
ではありません
==
を--print
の前に置くと、Current: = cap_net_raw+i
が表示されるので、前のエラーが説明されますが、ルートから切り替えるときに機能が失われるのではなく、secure-keep-caps
が修正するはずです。
私が見ることができるものから、execが呼び出されると、Effective(e)とPermitted(p)が失われます。これは予想されることですが、secure-keep-capsはそれらが失われるのを止めるべきだと思いました。何かが足りませんか。
私はより多くの研究を行っており、マニュアルをもう一度読んでいます。通常、e
およびp
機能は、ユーザーroot
から切り替える(またはsecure-noroot
を適用して、rootを通常のユーザーにする)と失われます。これはsecure-keep-caps
でオーバーライドできます。 exec
を呼び出すとき、私が知る限り、これは不変条件です。
私の知る限りでは、マニュアルに従って動作しています。私が知る限り、capsh
を使用して何か便利なことをする方法はありません。私の知る限り、機能を使用するには、ファイル機能を使用するか、exec
を使用しない機能認識プログラムを使用する必要があります。したがって、特権ラッパーはありません。
だから今私の質問は私が何を欠いているのか、何のためにcapsh
なのかです。
アンビエント機能に関する回答を追加しました。多分capsh
は継承された機能で使用することもできますが、これらを実行するには、実行可能ファイルに設定する必要があります。 capshがアンビエント機能なしで、または継承された機能を許可するためにどのように役立つかを確認できません。
バージョン:
capsh
パッケージからlibcap2-bin
バージョン1:2.22-1.2
git://git.debian.org/collab-maint/libcap2.git
から最新のcapsh
を取得して使用し始めました。uname -a
Linux richard-laptop 3.2.0-4-AMD64 #1 SMP Debian 3.2.65-1+deb7u2 x86_64 GNU/Linux
ユーザーランドは32ビットです。カーネルにバグ/機能がある可能性があります。いくつかの議論がありました:
何かが行われたとしても、それを修正することはできません。
誤解しないでください。現在の動作は安全です。しかし、それは非常に安全であるため、機能しているように見えるはずのものが邪魔になります。
編集: http://man7.org/linux/man-pages/man7/capabilities.7.html によると、新しい機能セットAmbientがあります(Linux 4.3以降)。これは必要なものを許可するように見えます。
機能はプロセスのプロパティです。従来、3つのセットがあります。
Rootとして実行されるプログラムは常に許可された効果的な機能をすべて備えているため、機能を「追加」しても目立った影響はありません。 (通常、継承可能な機能セットは空です。)setcap cap_net_raw+ep ping
を使用すると、このプログラムを実行するすべてのユーザーに対してこれらの機能をデフォルトで有効にします。
残念ながら、これらの機能は実行されたファイルにバインドされ、新しい子プロセスの実行後は保持されません。 Linux 4.3は アンビエント機能 を導入しました。これにより、機能を子プロセスに継承できます(execve()中の機能の変換capabilities(7) も参照)。
機能を操作するときは、次の落とし穴に注意してください。
--keep=1
オプションを使用できます。 capsh
のセットをクリアしないようにします。Libcap 2.26以降、capsh
プログラムは、--addamb
_(commit )などのオプションを介してアンビエント機能を変更する機能を獲得しました。オプションの順序は重要です。使用例:
Sudo capsh --caps="cap_net_raw+eip cap_setpcap,cap_setuid,cap_setgid+ep" \
--keep=1 --user=nobody --addamb=cap_net_raw -- \
-c "./ping -c1 127.0.0.1"
ヒント:capsh
コマンドラインの任意の場所に--print
オプションを追加して、現在の機能の状態を確認できます。
注:cap_setpcap
は--addamb
に必要ですが、cap_setuid,cap_setgid
は--user
オプションに必要です。
Lekensteynの答えは正確で完全なようですが、周囲の機能セットが解決する問題を強調するために、別の角度から別の説明を提供しようと思います。
Sudo capsh --user=<some_user> --
を実行すると、機能が再計算(および削除される可能性)する2つの重要なシステムコールがあります。
setuid
:man capabilities
によると:SECBIT_KEEP_CAPSこのフラグを設定すると、1つ以上の0 UIDを持つスレッドが、すべてのUIDをゼロ以外の値に切り替えたときに、その機能を保持できます。このフラグが設定されていない場合、そのようなUIDスイッチにより、スレッドはすべての機能を失います。
つまり、上記のcapsh
コマンドでは、setuid
システムコール中にSECBIT_KEEP_CAPSが設定されていることを確認する必要があります。そうしないと、すべての機能が失われます。これは--keep=1
が行うことです。したがって、コマンドはSudo capsh --user=<some_user> --keep=1 --
になります
execve
:--keep=1
オプションを使用すると、すべての機能セット(有効、許可、継承可能)が保持されますp untilexecve
システムコールですが、execve
により機能が再計算されます(非rootユーザー)も同様ですが、それほど明白ではありません。つまり、アンビエント機能セットの追加前は、execve
呼び出しの後に機能がスレッドの「許可された」セットに含まれるようにするため、次のいずれかです。
setcap cap_net_raw+p /bin/bash
で実行できます。これを行うと、スレッドの機能セット(境界セット以外)が無効になるため、演習全体が役に立たなくなります。setcap cap_net_raw+i
でうまくいくと思うかもしれませんが、execve
によって、権限のないユーザー(現在、setuid
のおかげです)から呼び出されたときに、スレッドの継承できない権限が削除されることがわかります。したがって、非特権ユーザーとしてこの条件を満たす方法はありません。Linux 4.3で導入されたアンビエント機能により、権限のないユーザーがsetuid
に続いてexecve
を使用した後でもスレッドがその機能を保持できるようになりますファイル機能に依存する必要はありません。