From 3fd5815677d3a7c65d489fbe651854950f80cf7c Mon Sep 17 00:00:00 2001 From: Dpeta <69427753+Dpeta@users.noreply.github.com> Date: Tue, 14 Mar 2023 15:08:58 +0100 Subject: [PATCH] Remove libseccomp (silly) --- README.md | 4 - libseccomp.py | 245 -------------------------------------------------- pesterchum.py | 39 -------- 3 files changed, 288 deletions(-) delete mode 100644 libseccomp.py diff --git a/README.md b/README.md index 32200a9..02098f9 100644 --- a/README.md +++ b/README.md @@ -92,9 +92,6 @@ Pesterchum is a Python script. This means that as long as you have Python instal - Useful for Linux systems that don't meet the Qt6 requirements, as Qt5 Multimedia has a GStreamer dependency. - (Optional) [certifi] can provide alternative root certificates for TLS certificate validation. - Useful for MacOS, as Python doesn't use the system-provided certificates because of MacOS' outdated SSL library. Also miscellaneous systems without usable root certificates. - - (Optional) [libseccomp] and its Python bindings on Linux let Pesterchum apply seccomp-bpf restrictions on itself. - - Packages on Arch: ``libseccomp python-libseccomp`` - - Packages on Debian: ``libseccomp2 python-seccomp`` ### WALKTHROUGH @@ -123,7 +120,6 @@ Pesterchum is a Python script. This means that as long as you have Python instal [pygame-ce]: https://pypi.org/project/pygame-ce/ [certifi]: https://pypi.org/project/certifi/ [GStreamer]: https://gstreamer.freedesktop.org/ -[libseccomp]: https://github.com/seccomp/libseccomp/ ## FREEZE / BUILD Here's a quick guide on how to freeze Pesterchum, (that is, packaging it with python as an executable). :3 diff --git a/libseccomp.py b/libseccomp.py deleted file mode 100644 index 80a00cb..0000000 --- a/libseccomp.py +++ /dev/null @@ -1,245 +0,0 @@ -"""Functions for Applying a seccomp filter on Linux. - -This prevents the process from using certain system calls, which has some security benefits. -Since Python and Qt use many calls and are pretty high-level, things are prone to breaking though. -Certain features like opening links almost always break. - -Uses libseccomp's Python bindings, which sadly aren't available on PyPi (yet). -Check your distro's package manager for python-libseccomp (Arch) or python3-seccomp (Debian). - -For info on system calls referencing software that uses seccomp like firejail/flatpak is useful. -Bindings documentation: https://github.com/seccomp/libseccomp/blob/main/src/python/seccomp.pyx -""" -import os -import logging -import threading - -try: - import seccomp -except ImportError: - seccomp = None - -pesterchum_log = logging.getLogger("pchumLogger") - - -def load_seccomp_blacklist(): - """Applies a selective seccomp filter only disallows certain risky calls. - - Should be less likely to cause issues than a full-on whitelist.""" - if seccomp is None: - pesterchum_log.warning( - "Failed to import seccomp, verify you have" - " python-libseccomp (Arch) or python3-seccomp (Debian) installed." - " If this is a pyinstaller/cx_freeze build, it may also be a linking issue." - ) - return - # Allows all calls by default. - sec_filter = seccomp.SyscallFilter(defaction=seccomp.ALLOW) - - # Deny all socket domains other than AF_UNIX and and AF_INET. - sec_filter.add_rule(seccomp.ERRNO(1), "socket", seccomp.Arg(0, seccomp.LT, 1)) - sec_filter.add_rule(seccomp.ERRNO(1), "socket", seccomp.Arg(0, seccomp.GT, 2)) - - # Fully deny these calls. - for call in CALL_BLACKLIST: - try: - sec_filter.add_rule(seccomp.ERRNO(1), call) - except RuntimeError: - pesterchum_log.warning("Failed to load deny '%s' call seccomp rule.", call) - - sec_filter.load() - - -def load_seccomp_whitelist(): - """Applies a restrictive seccomp filter that disallows most calls by default.""" - if seccomp is None: - pesterchum_log.error( - "Failed to import seccomp, verify you have" - " python-libseccomp (Arch) or python3-seccomp (Debian) installed." - " If this is a pyinstaller/cx_freeze build, it may also be a linking issue." - ) - return - # Violation gives "Operation not permitted". - sec_filter = seccomp.SyscallFilter(defaction=seccomp.ERRNO(1)) - # Full access calls - for call in CALL_WHITELIST: - try: - sec_filter.add_rule(seccomp.ALLOW, call) - except RuntimeError: - pesterchum_log.warning("Failed to load allow '%s' call seccomp rule.", call) - - # Allow only UNIX and INET sockets, see the linux manual and source on socket for reference. - # Arg(0, seccomp.EQ, 1) means argument 0 must be equal to 1, 1 being the value of AF_UNIX. - # Allow AF_UNIX - sec_filter.add_rule(seccomp.ALLOW, "socket", seccomp.Arg(0, seccomp.EQ, 1)) - # Allow AF_INET - sec_filter.add_rule(seccomp.ALLOW, "socket", seccomp.Arg(0, seccomp.EQ, 2)) - - # Python/Qt might close itself via kill call in case of error. - sec_filter.add_rule(seccomp.ALLOW, "kill", seccomp.Arg(0, seccomp.EQ, os.getpid())) - sec_filter.add_rule( - seccomp.ALLOW, "tgkill", seccomp.Arg(1, seccomp.EQ, threading.get_native_id()) - ) - - # Allow openat as long as it's not in R+W mode. - # We can't really lock down open/openat further without breaking everything, - # even though it's one of the most important calls to lock down. - # Could probably allow breaking out of the sandbox in the case of full-on RCE/ACE. - sec_filter.add_rule(seccomp.ALLOW, "openat", seccomp.Arg(2, seccomp.NE, 2)) - - sec_filter.load() - - -# Required for Pesterchum to function normally. -# We don't call most of these directly, there's a lot of abstraction with Python and Qt. -CALL_WHITELIST = [ - "access", # Files - "brk", # Required - "clone3", # Required - "close", # Sockets (Audio + Network) - "connect", # Sockets (Audio + Network) - "exit", # Exiting - "exit_group", # Exiting - "fallocate", # Qt - "fcntl", # Required (+ Audio) - "fsync", # Fsync log files - "ftruncate", # Required - "futex", # Required - "getcwd", # Get working directory - "getdents", # Files? Required. - "getgid", # Audio - "getpeername", # Connect - "getpid", # Audio - "getrandom", # Malloc - "getsockname", # Required for sockets - "getsockopt", # Required for sockets - "getuid", # Audio - "ioctl", # Socket/Network - "lseek", # Files - "memfd_create", # Required (For Qt?) - "mkdir", # Gotta make folderz sometimez - "mmap", # Audio - "mprotect", # QThread::start - "munmap", # Required (segfault) - "newfstatat", # Required (Audio + Path?) - "pipe2", # Audio - "poll", # Required for literally everything - "pselect6", # Sockets/Network - "read", # It's read :3 - "readlink", # Files - "recv", # Network - "recvfrom", # Network + DNS - "recvmsg", # Sockets (incl. Audio + Network) - "rseq", # Required - "rt_sigprocmask", # Required (segfault) - "select", # Useful for sockets - "sendmmsg", # Network - "sendmsg", # Sockets - "sendto", # Eternal eepy!! Sockets + required for waking up mainloop. - "setsockopt", # Audio - "statx", # File info - "uname", # Required - "write", # Required -] - -# Blacklists of calls we should be able to safely deny. -# Setuid might be useful to drop privileges. -SETUID = [ - "setgid", - "setgroups", - "setregid", - "setresgid", - "setresuid", - "setreuid", - "setuid", -] -SYSTEM = [ - "acct", - "bpf", - "capset", - "chown", - "chroot", - "fanotify_init", - "fsconfig", - "fsmount", - "fsopen", - "fspick", - "kexec_file_load", - "kexec_load", - "lookup_dcookie", - "mount", - "move_mount", - "nfsservctl", - "open_by_handle_at", - "open_tree", - "perf_event_open", - "personality", - "pidfd_getfd", - "pivot_root", - "pivot_root", - "process_vm_readv", - "process_vm_writev", - "ptrace", # <-- Important - "quotactl", - "reboot", - "rtas", - "s390_runtime_instr", - "setdomainname", - "setfsuid", - "sethostname", - "swapoff", - "swapon", - "sys_debug_setcontext", - "umount", - "umount2", - "vhangup", -] -CALL_BLACKLIST = SYSTEM # + SETUID - -""" -# Optional -EXTRA_CALLS = [ - "mlock", - "munlock", - "socketcall", - "socketpair", - "readlink", - "getsockname", - "getpeername", - "writev", - "open", - "time", - "listen", -] -# Required on launch -LAUNCH_CALLS = [ - "prctl", - "faccessat", - "faccessat2", - "pwrite64", -] -# Required before full initialize -PRE_INITIALIZE_CALLS = [ - "bind", - "eventfd2", - "getegid", - "geteuid", - "getresgid", - "getresuid", - "gettid", - "recvmmsg", - "restart_syscall", - "rt_sigaction", - "rt_sigreturn", - "sched_getaffinity", - "sched_getattr", - "sched_setattr", - "shutdown", - "umask", -] -# Required for opening links, but opening links still doesn't work anyway. -LINK_CALLS = [ - "wait4", # for links? - "clone", # for links? -] -""" diff --git a/pesterchum.py b/pesterchum.py index f7f1055..c1c6a05 100755 --- a/pesterchum.py +++ b/pesterchum.py @@ -19,9 +19,6 @@ import ostools import nickservmsgs import pytwmn -if ostools.isLinux(): - import libseccomp - # import console from user_profile import ( userConfig, @@ -114,21 +111,6 @@ parser.add_argument( parser.add_argument( "--nohonk", action="store_true", help="Disables the honk soundeffect 🤡📣" ) -if ostools.isLinux(): - parser.add_argument( - "--no-seccomp", - action="store_true", - help=("Disable seccomp completely. (do this if it causes issues)"), - ) - parser.add_argument( - "--strict-seccomp", - action="store_true", - help=( - "Apply a stricter seccomp-bpf filter that only allows required system calls." - " This breaks certain features like opening links." - " (Requires Linux and libseccomp's Python bindings.)" - ), - ) # Set logging config section, log level is in oppts. # Logger @@ -1692,22 +1674,6 @@ class PesterWindow(MovingWindow): if ostools.isLinux(): # Set no_new_privs bit. self.set_no_new_privs() - # Activate seccomp. - self.seccomp(options) - - def seccomp(self, options): - """Load seccomp-bpf filter depending on arguments passed.""" - if "no-seccomp" in options: - if options["no-seccomp"]: - return - try: - libseccomp.load_seccomp_blacklist() # Load blacklist filter by default - if "strict-seccomp" in options: - if options["strict-seccomp"]: - libseccomp.load_seccomp_whitelist() # Load whitelist filter if enabled - except RuntimeError: - # We probably tried to interact with a call not available on this kernel. - PchumLog.exception("") @QtCore.pyqtSlot(str, str) def updateMsg(self, ver, url): @@ -4592,11 +4558,6 @@ class MainProgram(QtCore.QObject): # Disable honks if args.nohonk: options["honk"] = False - if ostools.isLinux(): - if args.strict_seccomp: - options["strict-seccomp"] = True - if args.no_seccomp: - options["no-seccomp"] = True except Exception as e: print(e) return options