服务器权限控制的核心是“该不该由这个身份做”,而非“能不能做”;Linux通过内核在系统调用入口校验进程凭证与capabilities实施强制限制,Windows依赖令牌权限与会话隔离形成硬边界,跨平台均要求权限降级必须在系统调用发起前完成。

服务器权限控制的核心不是“能不能做”,而是“该不该由这个身份做”。系统调用层面的权限限制,直接决定进程能否访问硬件、读写内核对象、切换用户上下文或跨会话通信。绕过这一层,再细的角色权限设计也形同虚设。
Linux:从系统调用入口掐断越权行为
普通用户进程默认无法执行某些敏感系统调用(如mount、setuid、ptrace),这不是靠文件权限拦住的,而是由内核在syscall入口校验当前进程的凭证(cred)和能力(capability)。
- 用
capsh --print查看当前进程拥有的capabilities,避免盲目用sudo掩盖能力缺失 - 给程序只加必要能力,例如仅需绑定1024以下端口:
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/myserver - 禁用危险调用:通过
seccomp-bpf过滤器拦截openat对/etc/shadow的访问,比chmod更底层
Windows:令牌权限与会话隔离是硬边界
服务进程运行在Session 0,而用户桌面在Session 1+,这不仅是显示问题——它意味着服务默认没有访问用户窗口站(WinSta0)、桌面对象(Default)或注册表HKEY_CURRENT_USER的令牌权限。
- 不要依赖“允许服务与桌面交互”(已弃用),改用
WTSQueryUserToken+CreateProcessAsUser在目标Session中启动UI进程 - 若需读取当前登录用户的配置,先调用
WTSGetActiveConsoleSessionId获取会话ID,再用ImpersonateLoggedOnUser临时模拟该用户令牌 - 注册表操作涉及
HKEY_CURRENT_USER时,必须确保线程运行在对应用户上下文中,否则会静默失败或落到默认配置
跨平台共性:权限降级必须在调用前完成
无论Linux的setuid还是Windows的RevertToSelf,权限提升/降级都发生在系统调用发起前。一旦以高权限身份进入内核,后续所有子调用都继承该上下文——不存在“中间降权”。
- Linux下:用
prctl(PR_SET_NO_NEW_PRIVS, 1)阻止后续execve获得新权限,配合seccomp使用更稳妥 - Windows下:服务启动UI程序后,应立即调用
SetThreadToken(NULL)清除模拟令牌,防止后续误用 - 容器环境:Docker的
--user参数只影响初始进程,若程序自行调用setuid,仍可能提权——需配合no-new-privileges: true运行时限制
系统调用权限不是配置项,是运行时的强制检查点。控制它,等于握住了进程行为的总闸门。











