$ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -y libcap2-bin
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">update
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -y libcap2-bin
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">update
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -y libcap2-bin
-weight: 600;">sudo getcap -r / 2>/dev/null
-weight: 600;">sudo getcap -r / 2>/dev/null
-weight: 600;">sudo getcap -r / 2>/dev/null
-weight: 600;">sudo find / -xdev -perm -4000 -type f -printf '%M %u %g %p\n'
-weight: 600;">sudo find / -xdev -perm -4000 -type f -printf '%M %u %g %p\n'
-weight: 600;">sudo find / -xdev -perm -4000 -type f -printf '%M %u %g %p\n'
-weight: 600;">sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/myapp
-weight: 600;">sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/myapp
-weight: 600;">sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/myapp
getcap /usr/local/bin/myapp
getcap /usr/local/bin/myapp
getcap /usr/local/bin/myapp
/usr/local/bin/myapp cap_net_bind_service=ep
/usr/local/bin/myapp cap_net_bind_service=ep
/usr/local/bin/myapp cap_net_bind_service=ep
# /etc/systemd/system/myapp.-weight: 500;">service
[Unit]
Description=My app
After=network.target [Service]
User=myapp
Group=myapp
ExecStart=/usr/local/bin/myapp
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
Restart=on-failure [Install]
WantedBy=multi-user.target
# /etc/systemd/system/myapp.-weight: 500;">service
[Unit]
Description=My app
After=network.target [Service]
User=myapp
Group=myapp
ExecStart=/usr/local/bin/myapp
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
Restart=on-failure [Install]
WantedBy=multi-user.target
# /etc/systemd/system/myapp.-weight: 500;">service
[Unit]
Description=My app
After=network.target [Service]
User=myapp
Group=myapp
ExecStart=/usr/local/bin/myapp
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
Restart=on-failure [Install]
WantedBy=multi-user.target
-weight: 600;">sudo -weight: 500;">systemctl daemon-reload
-weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable --now myapp.-weight: 500;">service
-weight: 600;">sudo -weight: 500;">systemctl daemon-reload
-weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable --now myapp.-weight: 500;">service
-weight: 600;">sudo -weight: 500;">systemctl daemon-reload
-weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable --now myapp.-weight: 500;">service
-weight: 500;">systemctl cat myapp.-weight: 500;">service
-weight: 500;">systemctl show myapp.-weight: 500;">service -p User -p Group -p AmbientCapabilities -p CapabilityBoundingSet -p NoNewPrivileges
-weight: 500;">systemctl cat myapp.-weight: 500;">service
-weight: 500;">systemctl show myapp.-weight: 500;">service -p User -p Group -p AmbientCapabilities -p CapabilityBoundingSet -p NoNewPrivileges
-weight: 500;">systemctl cat myapp.-weight: 500;">service
-weight: 500;">systemctl show myapp.-weight: 500;">service -p User -p Group -p AmbientCapabilities -p CapabilityBoundingSet -p NoNewPrivileges
-weight: 600;">sudo setcap -r /usr/local/bin/myapp
-weight: 600;">sudo setcap -r /usr/local/bin/myapp
-weight: 600;">sudo setcap -r /usr/local/bin/myapp
getcap /usr/local/bin/myapp
getcap /usr/local/bin/myapp
getcap /usr/local/bin/myapp
getcap "$(command -v ping)" 2>/dev/null || true
stat -c '%A %U:%G %n' "$(command -v ping)"
sysctl net.ipv4.ping_group_range 2>/dev/null || true
getcap "$(command -v ping)" 2>/dev/null || true
stat -c '%A %U:%G %n' "$(command -v ping)"
sysctl net.ipv4.ping_group_range 2>/dev/null || true
getcap "$(command -v ping)" 2>/dev/null || true
stat -c '%A %U:%G %n' "$(command -v ping)"
sysctl net.ipv4.ping_group_range 2>/dev/null || true
-weight: 600;">sudo setcap 'cap_sys_admin=+ep' /usr/local/bin/myapp
-weight: 600;">sudo setcap 'cap_sys_admin=+ep' /usr/local/bin/myapp
-weight: 600;">sudo setcap 'cap_sys_admin=+ep' /usr/local/bin/myapp
-weight: 600;">sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/myapp
-weight: 600;">sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/myapp
-weight: 600;">sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/myapp
# file metadata
getcap /usr/local/bin/myapp # -weight: 500;">service policy
-weight: 500;">systemctl show myapp.-weight: 500;">service -p AmbientCapabilities -p CapabilityBoundingSet -p NoNewPrivileges # listener really came up on a privileged port
ss -ltnp '( sport = :80 )' # -weight: 500;">service identity
ps -o user,group,comm,args -C myapp
# file metadata
getcap /usr/local/bin/myapp # -weight: 500;">service policy
-weight: 500;">systemctl show myapp.-weight: 500;">service -p AmbientCapabilities -p CapabilityBoundingSet -p NoNewPrivileges # listener really came up on a privileged port
ss -ltnp '( sport = :80 )' # -weight: 500;">service identity
ps -o user,group,comm,args -C myapp
# file metadata
getcap /usr/local/bin/myapp # -weight: 500;">service policy
-weight: 500;">systemctl show myapp.-weight: 500;">service -p AmbientCapabilities -p CapabilityBoundingSet -p NoNewPrivileges # listener really came up on a privileged port
ss -ltnp '( sport = :80 )' # -weight: 500;">service identity
ps -o user,group,comm,args -C myapp - root bypasses normal permission checks
- non-root users do not - CAP_NET_BIND_SERVICE to bind to ports below 1024
- CAP_NET_RAW to use raw and packet sockets
- CAP_SYS_ADMIN for a huge pile of admin operations - avoid setuid root when one small privilege will do
- avoid running long-lived services as root when a bounded capability is enough
- verify what you changed, instead of assuming it is safe - executables with file capabilities
- executables with the setuid bit - CAP_NET_BIND_SERVICE - /usr/bin/python3
- /usr/bin/node
- /usr/bin/bash - put the capability on a dedicated compiled binary
- use a -weight: 500;">service manager such as systemd to grant the capability to one -weight: 500;">service
- front the app with a reverse proxy that already handles privileged ports - privilege is declared in the unit, not hidden on the file
- CapabilityBoundingSet= limits what the -weight: 500;">service can ever retain
- AmbientCapabilities= passes the needed capability to a non-root process
- NoNewPrivileges=true helps prevent gaining more privilege later - you have one dedicated executable
- the privilege should travel with that executable
- the program may run outside systemd - the program is a -weight: 500;">service you manage
- you want the privilege policy next to the rest of the -weight: 500;">service definition
- you want a clean rollback by editing the unit rather than modifying executable metadata - for services, prefer systemd
- for one-off dedicated binaries, file capabilities can be fine
- for shared interpreters, avoid file capabilities - some ship ping with file capabilities
- some historically used setuid
- some rely on kernel support for unprivileged ICMP echo sockets with net.ipv4.ping_group_range - prefer the narrowest capability that solves the problem
- be suspicious of CAP_SYS_ADMIN
- treat capability changes like a security change, not a convenience tweak
- document why the capability exists
- test as the unprivileged -weight: 500;">service user, not only as root - identify what the program actually needs to do
- map that to the smallest capability that matches
- prefer -weight: 500;">service-level controls if the app is systemd-managed
- verify the file or -weight: 500;">service configuration after the change
- run a real functional test as the target non-root user
- document the reason so the next admin does not "fix" it back to root - the application still needs broad filesystem access that effectively requires root
- you are tempted to use CAP_SYS_ADMIN
- the program is launched through a shared interpreter
- a reverse proxy, socket activation, or a small privileged helper would be cleaner - Linux capabilities overview: https://man7.org/linux/man-pages/man7/capabilities.7.html
- setcap(8) manual: https://man7.org/linux/man-pages/man8/setcap.8.html
- getcap(8) manual: https://man7.org/linux/man-pages/man8/getcap.8.html
- systemd execution environment, including AmbientCapabilities= and CapabilityBoundingSet=: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
- Linux ICMP and ping_group_range: https://man7.org/linux/man-pages/man7/icmp.7.html