aka my homepage :P
PPy - privileged python wrapper
26 dec 2009
The thing is very simple - a C binary, designed as a drop-in replacement for python binary in shebangs or command line for the scripts that need elevated (or just different) privileges then the ones they've been started with. Essentially, it's a remake of suid perl wrapper, but based on capabilities(7) instead of suid.
POSIX Caps fragment root privileges into many subsets and prevent unrestricted propagnation via exec. In a nutshell, when you need to, say, backup whole file system, you have two choices:
Just scan through man 7 capabilities and you'll see how nice they are ;)
This wrapper allows scripts with posix caps set on them (and fairly secure mode) to retain these caps as permitted, but not immediately-effective, regardless of fs flag.
Note that the wrapper itself need to be either suid root or inherit capabilities via some other way (all+ep, for instance) to get full permitted-set, and needs python binary with used caps set as inherited ('all=i' + root:priveleged_group:0750 setup should be fairly secure, you can clear inheritable set to be on the safe side).
Also you'll need fairly recent kernel (>=2.6.25) with CONFIG_SECURITY_FILE_CAPABILITIES=y and CONFIG_(your_fs_of_choice)_FS_SECURITY=y.
setcap 'cap_dac_read_search=i' /path/to/capped/script.py
Setting dac_read_search capability to a file (via libcap binary).
#!/usr/bin/ppy from capng import * capng_get_caps_process() capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_READ_SEARCH) capng_apply(CAPNG_SELECT_CAPS) import os print os.listdir('/root')
Should give you listing of the "/root" (normally not readable by user) if you've set dac_read_search cap onto the script file (see above).
Invocation from the command line.
Well, I bet it's easier to look at the source itself to understand it's operation 'cause it's quite straightforward, but since I've decided to pull this page together, might as well explain it here... in fact, it's just a couple of checks:
It's a whole lot less checks than in suid perl, but I'm just not that paranoid :P
There are no python-specific quirks in the wrapper itself, so it can be used with pretty much any interpreter, or just any app for that matter.
Also note that to make use of the capabilities, you'll need to set them in the effective set. I have a rant on how weird are python wrappers for these and my own implementation here.
Source is here. Use gcc ppy.c -o ppy -lcap-ng to build it.