在 Linux 系统安全中,符号链接(Symbolic Link)是一把双刃剑。它提供了路径跳转的便利,但也为符号链接劫持(Symlink Hijacking)和权限提升留下了后门。为了堵住这些漏洞,Linux 内核引入了 fs.protected_symlinks 参数。
1. 什么是 protected_symlinks?
protected_symlinks 是 Linux 内核的一项安全功能(自 3.6 版本引入),主要用于限制在特定条件下跟随符号链接的行为。其核心目的是防止低权限用户诱骗高权限进程(如 root 运行的 cron 任务或 Web 服务)去读写不该访问的文件。
如何查看与设置
- 查看状态:
cat /proc/sys/fs/protected_symlinks(1为开启,0为关闭)。 - 临时修改:
sysctl -w fs.protected_symlinks=0。 - 永久修改:在
/etc/sysctl.conf中添加fs.protected_symlinks = 1。
2. 触发拦截的“三位一体”条件
内核不会无缘无故拦截链接。只有当以下 三个条件同时满足 时,open() 系统调用才会返回 EACCES(权限被拒绝):
- 全局开关开启:
fs.protected_symlinks = 1。 - 处于危险目录:符号链接所在的父目录必须具有 粘滞位(Sticky Bit,
+t) 且对 所有人可写(World-writable)。典型的例子是/tmp和/var/tmp。 - 所有权不匹配:
- 链接的创建者 与 尝试读取链接的进程运行者 不一致。
- 且 链接的创建者 与 目标文件的所有者 不一致。
逻辑推论:如果你在自己的家目录(没有粘滞位)创建一个指向 root 文件的链接,该机制不会触发。内核认为私有目录是安全的,只有公共“垃圾场”才需要特别巡逻。
3. 实战案例:为什么 Web 服务器会报 404?
假设你在做一个 CTF 题目或渗透测试,场景如下:
- 环境:Python
http.server以用户hyh身份在/var/tmp运行。 - 目标:读取
/srv/ftp/pub/pass.txt(属主也是hyh,其他人不可读)。 - 尝试:你作为
www-data,在/var/tmp创建了一个文件链接ln -s /srv/ftp/pub/pass.txt my_link。
结果分析
当你请求 http://localhost:8080/my_link 时:
- 内核拦截:因为满足了上述三个条件(
/var/tmp有粘滞位、你是www-data、进程是hyh),内核拒绝open()操作。 - 代码伪装:在 Python 的
server.py源码中,所有OSError(包括权限拒绝)都会被try...except捕获并重定向为404 Not Found。这是一种安全策略:不告诉你“没权限”,而是告诉你“没这个文件”,防止泄露敏感路径的存在。
4. 绕过技巧:目录链接的“逻辑间隙”
这是 protected_symlinks 最有趣的地方:它对文件链接和目录链接的解析逻辑存在差异。
- 文件链接(直接打开):你直接访问链接,内核会检查“谁建立了这个链接”,检查失败,拦截。
- 目录链接(路径平移):如果你建立一个指向父目录的链接
ln -s /srv/ftp/pub pwn_dir,然后访问/pwn_dir/pass.txt:- 内核在解析路径组件时,将
pwn_dir视为一个位置跳板。 - 一旦跳转完成,后续的操作变成了“在
/srv/ftp/pub目录下打开pass.txt”。 - 此时,由于进程所有者(
hyh)和文件所有者(hyh)一致,内核认为这是合法的内部访问,不再触发针对链接所有者的校验。
- 内核在解析路径组件时,将
总结
fs.protected_symlinks 是 Linux 为了修补共享目录漏洞而设计的“补丁”。它虽然能有效防止简单的符号链接劫持,但在面对目录级链接跳转和进程 UID 权限重合时,仍可能被巧妙绕过。理解它的底层触发逻辑,是进行安全加固或漏洞利用的基础。
原文 https://blog.csdn.net/2301_79518550/article/details/159887444