10

Linux システムでは、ファイル機能を使用して setuid ビットを追加するよりも、ルート権限をより選択的に付与できます。詳細capabilities(7)については、を参照してください。これらはファイルの属性であり、プログラムを使用して読み取ることができますgetcap。これらの属性は Python でどのように取得できますか?

getcapたとえば、このような質問に答えるためにプログラムを実行するsubprocessことは可能ですが、非常に多くの機能を取得する場合は望ましくありません。

を使用して解決策を考案できるはずctypesです。このアプローチや、このタスクを容易にするライブラリに代わるものはありますか?

4

2 に答える 2

6

Python 3.3 にはos.getxattr. そうでない場合、ええ... 1つの方法はctypes、少なくとも生のものを取得するために、またはおそらく使用することですpyxattr

の場合pyxattr:

>>> import xattr
>>> xattr.listxattr("/bin/ping")
(u'security.capability',)
>>> xattr.getxattr("/bin/ping", "security.capability")
'\x00\x00\x00\x02\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

Python 3.3 のバージョンでは、 のos代わりに , をインポートするだけで、本質的に同じですxattrctypesただし、もう少し複雑です。

今、生の結果を取得しています。つまり、これら 2 つはテキスト属性を取得する場合にのみ最も役立ちます。しかし... ,自体getcapを通して同じアプローチを使用できます。libcap

import ctypes

libcap = ctypes.cdll.LoadLibrary("libcap.so")
cap_t = libcap.cap_get_file('/bin/ping')
libcap.cap_to_text.restype = ctypes.c_char_p
libcap.cap_to_text(cap_t, None)

それは私に与える:

'= cap_net_raw+p'

おそらくあなたにとってより便利です。

PS : ed 文字列をcap_to_text返すことに注意してください。mallocを使用して割り当てを解除するのはあなたの仕事ですcap_free

「バイナリ意味不明」についてのヒント:

>>> import struct
>>> caps = '\x00\x00\x00\x02\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> struct.unpack("<IIIII", caps)
(33554432, 8192, 0, 0, 0)

その中で8192、アクティブなビットは 13 番目だけです。にアクセスすると、が で定義されlinux/capability.hていることがわかります。CAP_NET_RAW13

これらすべての定数を含むモジュールを作成したい場合は、情報をデコードできます。ctypesしかし、単に+を使用するよりもはるかに面倒だと思いますlibcap

于 2014-02-04T19:31:30.220 に答える
0

ctypesリカルド・カルデネスの回答のコードを試しましたが、呼び出しの詳細が正しくないため、適切に機能しませんでした。getxattr(...)この問題により、切り詰められたパス文字列がの内部に渡され、間違ったアイテム (実際のパスではなく、ディレクトリまたはその他の最初のパス文字)libcapに対して間違った機能リストが返されました。/

Python 3.X でのstrとの違いを覚えて説明することは非常に重要です。bytesこのコードは Python 3.5/3.6 で正しく動作します:

#!/usr/bin/env python3

import ctypes
import os
import sys

# load shared library
libcap = ctypes.cdll.LoadLibrary('libcap.so')

class libcap_auto_c_char_p(ctypes.c_char_p):
    def __del__(self):
        libcap.cap_free(self)

# cap_t cap_get_file(const char *path_p)
libcap.cap_get_file.argtypes = [ctypes.c_char_p]
libcap.cap_get_file.restype  = ctypes.c_void_p

# char* cap_to_text(cap_t caps, ssize_t *length_p)
libcap.cap_to_text.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
libcap.cap_to_text.restype  = libcap_auto_c_char_p

def cap_get_file(path):
    cap_t = libcap.cap_get_file(path.encode('utf-8'))
    if cap_t is None:
        return ''
    else:
        return libcap.cap_to_text(cap_t, None).value.decode('utf-8')

print(cap_get_file('/usr/bin/traceroute6.iputils'))
print(cap_get_file('/usr/bin/systemd-detect-virt'))
print(cap_get_file('/usr/bin/mtr'))
print(cap_get_file('/usr/bin/tar'))
print(cap_get_file('/usr/bin/bogus'))

出力は次のようになります (存在しないもの、または機能が設定されていないものは、次のように返されます''

= cap_net_raw+ep
= cap_dac_override,cap_sys_ptrace+ep
= cap_net_raw+ep
于 2018-04-25T18:45:55.237 に答える