防止符号链接越权访问需多层协同防护:文件系统层严格控制目录权限并锁定高风险目录;Web服务层用Nginx的disable_symlinks指令限定解析路径;应用层通过is_link/readlink/realpath校验白名单;系统层加固权限与日志监控。

防止普通用户通过符号链接越权访问敏感文件,核心思路是切断解析路径、限制访问范围、强化权限边界。这不是单靠一个命令就能解决的问题,而是需要从文件系统层、运行时进程层和应用逻辑层协同设防。
严格控制符号链接所在目录的权限
普通用户若能在 Web 根目录、上传目录或临时目录中创建符号链接,就等于拿到了“跳板”。必须确保:
- Nginx/Apache/PHP-FPM 运行用户(如 www-data、nginx)对敏感路径(/etc/、/home/、/root/)无任何读、写、执行权限
- 静态资源目录(如 /var/www/static)本身及其父目录设置为 750 或 755,且禁止其他用户(others)写入(即不带 o+w)
- 上传目录等高风险位置可加锁:
chmod o-w /var/www/uploads或使用chattr +a(仅允许追加)防止 symlink 覆盖
在 Web 服务层启用路径逃逸拦截
Nginx 提供了 disable_symlinks 指令,专用于防御软链导致的路径穿越:
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- 只能用在
location或server块内,不能放在http全局块 - 必须配合
from=指定可信基目录,例如:disable_symlinks on from=/var/www/html/; - 它会检查整个路径解析链——包括所有中间软链接的目标——是否全部落在
from目录内;一旦跳出(如/var/www/html/../etc/passwd),直接返回 403 Forbidden - 注意:该指令只对 Nginx 自己读文件的行为生效(
root、alias、try_files),对proxy_pass或 PHP 的include无效
在应用层做符号链接安全校验
PHP 等脚本语言中,file_exists() 无法识别链接指向是否合法,容易被欺骗。应改用更严谨的判断方式:
- 先用
is_link()判断是否为符号链接 - 再用
readlink()获取真实目标路径 - 最后用
realpath()展开并比对是否在白名单目录内,例如:$real = realpath($user_input); if (strpos($real, '/var/www/app/') !== 0) { die('Access denied'); } - 对关键操作(如
include、readfile、unlink)一律禁用相对路径拼接,强制限定根目录
系统级加固与监控
从操作系统层面收窄攻击面:
- 确认 /etc/shadow 权限为
600,且仅 root 和 shadow 组成员可访问;移除非必要 shadow 组用户 - 避免在用户可写目录(如
/tmp、/var/tmp)中运行高权限服务 - 开启 Nginx 错误日志记录(
error_log /var/log/nginx/error.log notice;),当disable_symlinks触发拦截时,日志会明确提示路径越界行为 - 定期审计用户家目录及公共目录中的符号链接:
find /home -type l -ls 2>/dev/null

















