[HOME] [DOWNLOAD] [DOCS] [BLOG] [SUPPORT] [TIPS] [ISSUES] [Priority Support]

Cpfpd data/options / control-port-filter-python hardening


#1

This thread is for discussion of service hardening for cpfpd and gathering data that makes it easier to set permissions.


#2

This is a basic attempt to figure out what syscalls are used by the process:

user@host:~$ strace -cf /usr/sbin/cpfpd restart Process 11246 attached Process 11247 attached % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 85.23 0.030436 0 65710 65529 close 11.20 0.004000 55 73 rt_sigaction 2.20 0.000787 3 265 read 0.99 0.000353 3 126 mmap2 0.38 0.000136 0 902 727 open 0.00 0.000000 0 27 write 0.00 0.000000 0 11 11 link 0.00 0.000000 0 3 unlink 0.00 0.000000 0 1 execve 0.00 0.000000 0 1 chdir 0.00 0.000000 0 4 time 0.00 0.000000 0 10 10 access 0.00 0.000000 0 1 1 kill 0.00 0.000000 0 1 dup 0.00 0.000000 0 18 brk 0.00 0.000000 0 6 2 ioctl 0.00 0.000000 0 1 umask 0.00 0.000000 0 3 dup2 0.00 0.000000 0 1 getppid 0.00 0.000000 0 1 setsid 0.00 0.000000 0 13 gettimeofday 0.00 0.000000 0 4 2 readlink 0.00 0.000000 0 85 munmap 0.00 0.000000 0 2 clone 0.00 0.000000 0 2 uname 0.00 0.000000 0 14 mprotect 0.00 0.000000 0 6 _llseek 0.00 0.000000 0 10 select 0.00 0.000000 0 1 rt_sigprocmask 0.00 0.000000 0 1 getcwd 0.00 0.000000 0 1 getrlimit 0.00 0.000000 0 247 188 stat64 0.00 0.000000 0 7 lstat64 0.00 0.000000 0 257 fstat64 0.00 0.000000 0 2 getuid32 0.00 0.000000 0 2 getgid32 0.00 0.000000 0 1 geteuid32 0.00 0.000000 0 1 getegid32 0.00 0.000000 0 1 setuid32 0.00 0.000000 0 1 setgid32 0.00 0.000000 0 4 getdents64 0.00 0.000000 0 2 fcntl64 0.00 0.000000 0 1 futex 0.00 0.000000 0 1 set_thread_area 0.00 0.000000 0 1 set_tid_address 0.00 0.000000 0 2 openat 0.00 0.000000 0 3 set_robust_list 0.00 0.000000 0 3 prlimit64 0.00 0.000000 0 1 1 getsockopt ------ ----------- ----------- --------- --------- ---------------- 100.00 0.035712 67841 66471 total user@host:~$ strace -cf /usr/sbin/cpfpd usage: cpfpd start|stop|restart % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 43.09 0.000290 1 250 read 21.99 0.000148 2 76 munmap 17.98 0.000121 1 165 close 16.94 0.000114 0 890 727 open 0.00 0.000000 0 2 write 0.00 0.000000 0 2 unlink 0.00 0.000000 0 1 execve 0.00 0.000000 0 4 time 0.00 0.000000 0 10 10 access 0.00 0.000000 0 12 brk 0.00 0.000000 0 6 2 ioctl 0.00 0.000000 0 1 gettimeofday 0.00 0.000000 0 4 2 readlink 0.00 0.000000 0 1 uname 0.00 0.000000 0 14 mprotect 0.00 0.000000 0 6 _llseek 0.00 0.000000 0 68 rt_sigaction 0.00 0.000000 0 1 rt_sigprocmask 0.00 0.000000 0 1 getcwd 0.00 0.000000 0 1 getrlimit 0.00 0.000000 0 117 mmap2 0.00 0.000000 0 236 188 stat64 0.00 0.000000 0 7 lstat64 0.00 0.000000 0 244 fstat64 0.00 0.000000 0 1 getuid32 0.00 0.000000 0 1 getgid32 0.00 0.000000 0 1 geteuid32 0.00 0.000000 0 1 getegid32 0.00 0.000000 0 4 getdents64 0.00 0.000000 0 2 fcntl64 0.00 0.000000 0 1 futex 0.00 0.000000 0 1 set_thread_area 0.00 0.000000 0 1 set_tid_address 0.00 0.000000 0 2 openat 0.00 0.000000 0 1 set_robust_list ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000673 2135 929 total

#3

Thanks to systemd.exec much confinement of cpfpd can be easily done. These configuration additions to /lib/systemd/system/control-port-filter-python.service bring:

syscall whitelisting of only those calls on there.
/usr /boot and /etc are read-only.
access to /home /run/user is denied.
turns off all physical device access.

Settings have been tested as working.

That’s a great start :wink: :smiley: and even more tightening up is possible as more features can be tried.

Troubadour please double check that cpfpd is running fine before adding these settings to the .service file.

PrivateDevices=true

ProtectSystem=full
ProtectHome=true

NoNewPrivileges=true

SystemCallFilter=close
SystemCallFilter=open
SystemCallFilter=link
SystemCallFilter=access
SystemCallFilter=kill
SystemCallFilter=ioctl
SystemCallFilter=readlink
SystemCallFilter=stat64
SystemCallFilter=getsockopt

SystemCallArchitectures=native


#4

systemd.exec blogpost goes into a little more detail than manpage:
http://0pointer.de/blog/projects/security.html

Way to check if the restrictions are taking effect by cutting down whitelisted calls to see if the process fails (it should):
https://www.mail-archive.com/systemd-devel@lists.freedesktop.org/msg32389.html


#5

cpfpd pull requests:

Deny reads to interpreter:

More hardening options enabled:


#6

https://phabricator.whonix.org/T360


#7
Deny reads to interpreter: https://github.com/Whonix/control-port-filter-python/pull/1
The line [code]/usr/bin/python{2,3}.[0-7]* r,[/code] is generated by aa-genprof, as standard when it encounters a python script, I guess. It's not needed in cpfpd profile so, we don't have to deny it. It was simply removed in https://github.com/troubadoour/control-port-filter-python/commit/e3dd6731e2570abebc370851bdc45fb12973353d.

torbrowser-launcher probably has to read /usr/bin/python, but it can be safely denied without altering the functioning of the program.

More hardening options enabled: https://github.com/Whonix/control-port-filter-python/pull/2
seccomp' SystemCallFilter looks interesting, whitelisting the system calls allowed to the process, much like AppApmor is doing with the files.

Have tested cpfpd with the modified unit file in https://github.com/HulaHoopWhonix/control-port-filter-python/commit/c86b9ed6ffda98b3ca3b1a4235230f8df44b2076. It works. The trouble (or lack of) starts when I try to harden it further, removing “permissions”. At this moment, the only allowed system call is ‘kill’, which is not much, but control-port-filter-python.service is still restarting without issue. Am I missing something?


#8

systemctl – version reports

systemd 215 +PAM +AUDIT +SELINUX +IMA +SYSVINIT +LIBCRYPTSETUP +GCRYPT +ACL +XZ -SECCOMP -APPARMOR
-SECCOMP should explain it, and -APPARMOR https://phabricator.whonix.org/T355


#9
It works. The trouble (or lack of) starts when I try to harden it further, removing "permissions". At this moment, the only allowed system call is 'kill', which is not much, but control-port-filter-python.service is still restarting without issue. Am I missing something?

No that’s great. I used strace to give me a rough idea of what the minimal syscalls it must have to function and you discovered it needs even less than what I thought.


#10

I’m not sure that seccomp is enabled in systemd. cpfpd opens and closes its configuration file, starts a server for the requests, opens a socket to the control port… That’s a lot of system calls. To be checked.

Perhaps nothing new to you, but Firejail Seccomp looks like an good contender in this field. It was added very recently to the Debian FTP archive (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=777671). Available in sid only, not in Debian stretch / testing.

From the firs look: amongst some features, it uses secomp sytem call filters (default blacklist, can be expanded or used along a whitelist), it’s configurable with profiles, there is a --private option that mounts /home and /root in in a tmp file system, destroyed when the sanbox is closed… AND it’s compatible with AppArmor.

It’s very easy to use. The browser I’m using to write this was started with

Tor Browser is still contained by AppArmor.

Using start-tor-browser and not start-tor-browser.desktop because the latter is detached and the sandbox parent process terminates.

The --debug option gives a fair idea of what the default installed version is doing.


#11

Looks like Debian jessie’s version of systemd comes without seccomp support. Debian sid currently contains a recent enough version. This will likely easily be possible once we’re based on Debian stretch.

Source:


#12

I misunderstood what you were pointing out Troubadour, but now I opened a ticket to keep track of it for Debian Stretch. https://phabricator.whonix.org/T362


#13

re-enable tor-controlport-filter.service systemd hardening:
https://phabricator.whonix.org/T631