ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

没有高危漏洞也能被攻击?深入解析服务器配置与权限安全风险

没有高危漏洞也能被攻击?深入解析服务器配置与权限安全风险 引言当漏扫报告全绿攻击者却已经落地很多团队的安全运营止步于一件事把 Nessus、AWVS、Trivy 的报告刷到“无高危”。补丁打了镜像扫了WAF 上了看起来固若金汤。但真实的入侵事件里一个反复出现的场景是攻击者根本没有利用任何一个 CVE。他可能只是发现了一个location /static配alias时漏掉的尾斜杠顺着路径穿越读到了一份.env可能只是在某个容器里摸到了挂载进来的/var/run/docker.sock也可能只是发现某个运维账号的sudo规则里带了*通配符然后从sudo tar一路走到 root。这些问题的共同点是它们不是漏洞而是配置与权限的语义缺陷。漏洞有编号、有补丁、有扫描规则配置缺陷没有编号只有上下文。扫描器看到的是一行alias /data/static/;它无法判断这行配置在你的业务路径下是否可被穿越。攻击者看到的则是一条从低权限到 root 的完整链条。这就是本文想讲清楚的事为什么“没有高危漏洞”不等于安全以及如何从配置与权限的维度重新构建防御。一个更直观的比喻是漏洞像门锁上已知的缺陷扫描器能告诉你锁芯有没有被撬过的痕迹而配置缺陷像门根本没有关或者窗户开着却没人觉得那是入口。攻击者不会只盯着锁他会绕着房子走一圈推一推每一扇门拉一拉每一扇窗。配置与权限安全就是要把这些“门”和“窗”的状态纳入持续管理而不是只等锁厂发补丁。核心原理漏洞是有限集合配置是无限状态空间漏洞可枚举配置不可枚举CVE 的本质是“已知代码缺陷的指纹”。它有明确的版本区间、明确的触发条件因此可以被扫描器用特征匹配的方式批量发现。而配置是系统状态空间中的一个点操作系统版本、内核参数、文件权限位、服务监听地址、容器挂载、IAM 策略、sudoers 规则……这些维度组合出的状态数量是天文级的。安全配置的标准做法是“基线”——CIS Benchmark、等保要求、企业内部规范。但基线只能覆盖“已知的坏”无法覆盖“组合出来的坏”。chmod 755本身没问题可写目录本身也可能没问题但当“Web 根目录可写”遇上“Nginx 以 www-data 运行”遇上“存在一个可上传的接口”就构成了一条完整利用链。从数量级上看每年公开的 CVE 大约两万多个而一个 Linux 系统中仅文件权限位就有 12 位每个文件都可以独立设置进程有 UID/GID、Capabilities 有几十种、SELinux/AppArmor 策略、网络命名空间、挂载传播属性、cgroup 限制……这些维度交叉后配置状态几乎是无限组合。扫描器可以枚举已知漏洞但无法枚举“你的业务路径 你的文件内容 你的网络拓扑 你的权限组合”所构成的所有危险状态。更麻烦的是配置漂移。手工改一行配置、临时开一个调试端口、为了排障挂载一个宿主机目录这些操作往往不会回滚。容器镜像继承、IaC 模板覆盖、多环境差异都会让“基线”在运行时逐渐偏离。扫描器看到的是一张快照而攻击者面对的是一个持续变化的状态空间。权限模型的三要素理解配置风险先要理解权限模型身份Identity进程以谁的身份运行容器以哪个 UID 启动凭证Credential谁能读到密钥、Token、SSH 私钥凭证是否被硬编码、被提交进 Git授权边界Authorization Boundary从当前身份出发能到达哪些资源边界是否被隐式扩大SUID、sudo、Capabilities、挂载绝大多数“无漏洞入侵”的本质都是这三要素中的某一环出现了隐式越权。容器挂载 docker.sock等于把宿主机的 root 授权边界直接交给了容器内进程sudo配置里的NOPASSWD: /usr/bin/find等于把 root 权限通过一个“看似无害”的工具暴露出去。进一步拆解三要素身份如果容器以 root 运行一旦应用被 RCE攻击者直接就是容器内 root。如果容器以非 root 运行但挂载了 docker.sock攻击者仍然可以通过 Docker API 创建特权容器最终拿到宿主机 root。Kubernetes 中的securityContext.runAsUser、runAsNonRoot、allowPrivilegeEscalation都是控制身份的关键字段。凭证凭证泄露的途径远比想象中多。环境变量会被/proc/pid/environ、ps eww、docker inspect、崩溃转储、子进程继承一路带出去.env、docker-compose.yml、CI 日志、Git 历史都是高发区云环境中实例元数据服务IMDS也可能被 SSRF 利用获取临时凭证。凭证一旦泄露攻击者就可以用合法身份操作绕过所有基于漏洞的检测。授权边界授权边界不仅包括显式的 sudo、SUID、Capabilities还包括隐式的文件权限、挂载、cgroup、namespace 配置。例如/etc/cron.d可写意味着可以定时执行任意命令/proc/sys/kernel/core_pattern可写可以导致内核执行任意程序docker.sock可访问意味着可以控制整个 Docker daemon。授权边界的每一次隐式扩大都是一条潜在的提权路径。攻击链视角初始立足点往往不在应用层把入侵拆成四段初始立足点 → 权限提升 → 横向移动 → 持久化。漏扫关注的是第一段的应用层入口而配置风险在第一段暴露的管理接口、未授权 Redis、第二段SUID、sudo、Capabilities、第三段SSH 密钥复用、内网信任、第四段cron、systemd unit、容器 restart policy全都有分布。换句话说扫描器给你一张快照攻击者要的是一条链条。具体来看初始立足点除了应用漏洞未授权访问是重灾区。Redis 未授权写 SSH key、Elasticsearch 未授权读取数据、Docker API 未授权创建容器、K8s API 未授权创建 Pod、etcd 未授权读取集群密钥、数据库弱口令这些都不需要 CVE只需要一个暴露在公网且没有认证的服务。权限提升SUID 程序、sudo 通配符、Capabilities、内核漏洞、容器逃逸、计划任务、环境变量劫持、可写服务配置。配置风险在这一段尤其密集因为很多提权路径都是“合法功能被滥用”。横向移动SSH 密钥复用、内网信任、K8s service account token、云 IAM 角色、数据库连接字符串、CI/CD 凭证。攻击者拿到一个低权限立足点后会沿着信任关系向内网扩散。持久化cron、systemd unit、容器 restart policy、SSH authorized_keys、WebShell、后门账号、云 IAM 后门。持久化往往利用的是配置写入权限而不是漏洞。实战案例三个“零漏洞”的入侵路径案例一Nginx alias 路径穿越这是配置缺陷的教科书案例。当location前缀不以/结尾而alias指向的目录以/结尾时/static../这类请求会越过预期目录location /static { alias /data/static/; # 危险前缀无尾斜杠 }请求/static../etc/passwd会被拼接为/data/static/../etc/passwd即/data/etc/passwd。如果/data下恰好有可读的配置文件或者目录可写导致能上传文件这就是一条完整的 GetShell 路径。整个过程不涉及任何 CVE。更详细地解释Nginx 的location前缀匹配规则中location /static会匹配所有以/static开头的 URI包括/static../。而alias指令会用其参数替换掉location匹配到的部分。如果location是/static无尾斜杠alias是/data/static/有尾斜杠那么请求/static../etc/passwd中/static被替换为/data/static/剩下的../etc/passwd被拼接最终路径变成/data/static/../etc/passwd等价于/data/etc/passwd。如果/data下存在.env、config.php、id_rsa等敏感文件攻击者就能直接读取。路径穿越的变体还包括 URL 编码/static..%2fetc%2fpasswd某些中间件或代理在解码后仍然会触发同样的问题。如果/data/static目录可写攻击者甚至可以尝试上传../webshell.php到上级目录或者覆盖其他文件。实际渗透中曾有人通过/static../.env读到数据库密码进而登录后台再通过后台的上传功能 GetShell整条链路没有利用任何 CVE。修复方式很简单但必须成对处理要么location /static/ { alias /data/static/; }要么改用root指令。关键在于这类问题没有任何扫描器会在默认策略下报出来。注意root与alias的区别root /data;会拼接完整 URI即/data/static/...而alias会替换location匹配的部分。使用root时如果location /static/ { root /data; }请求/static/logo.png会映射到/data/static/logo.png这通常更符合直觉也更不容易出现尾斜杠问题。下面这段脚本可以批量审计这类配置#!/usr/bin/env python3nginx_alias_audit.py —— 检测 alias 路径穿越类配置缺陷importre,sys,pathlib LOC_REre.compile(r^\s*location\s(?Pprefix[^\s{])\s*\{,re.I)ALIAS_REre.compile(r^\s*alias\s(?Ppath[^;]);,re.I)defaudit(file_path:str):prefix,findingsNone,[]forlineno,lineinenumerate(pathlib.Path(file_path).read_text(errorsignore).splitlines(),1):ifm:LOC_RE.match(line):prefixm.group(prefix)elif(m:ALIAS_RE.match(line))andprefix:aliasm.group(path).strip()# 前缀无尾斜杠 alias 有尾斜杠 可被 ../ 逃逸ifnotprefix.endswith(/)andalias.endswith(/):findings.append((lineno,prefix,alias))returnfindingsfortargetinsys.argv[1:]or[/etc/nginx]:ppathlib.Path(target)filesp.rglob(*.conf)ifp.is_dir()else[p]forfinfiles:forlineno,prefix,aliasinaudit(str(f)):print(f[!]{f}:{lineno}location{prefix}- alias{alias}f前缀缺少结尾 /存在路径穿越风险)类似的问题也存在于 Apache 的Alias、IIS 的虚拟目录、Tomcat 的Context配置中。审计思路是一样的检查“前缀”与“目标目录”的尾斜杠是否匹配检查是否存在可被../逃逸的拼接逻辑。案例二容器内挂载 docker.sock 等于交出宿主机 root# 危险配置services:app:image:myapp:1.0volumes:-/var/run/docker.sock:/var/run/docker.sock# 等于把宿主机 root 权限交给容器任何能访问该 socket 的进程都可以创建特权容器并把宿主机根文件系统挂进去一步逃逸到宿主机 root。同样的问题还出现在privileged: true、cap_add: [SYS_ADMIN]、挂载/proc与/sys、hostPath挂载宿主机/等场景。这些配置在开发环境常被“为了方便”打开然后被原样带进生产。具体利用方式非常简单。假设攻击者已经通过应用漏洞进入容器容器内挂载了/var/run/docker.sock他只需要执行# 在容器内执行创建特权容器并挂载宿主机根目录dockerrun-v/:/host-italpinechroot/host或者dockerrun--privileged-v/:/host-italpinesh# 进入后 chroot /host 即可读写宿主机文件系统Docker daemon 通常以 root 运行socket 默认没有认证。任何能访问 socket 的进程都可以控制 daemon创建特权容器、挂载宿主机根目录、读取所有文件、写入 SSH key、安装后门。整个过程不需要任何 CVE。其他高危配置还包括privileged: true容器获得几乎所有 Capabilities可以访问宿主机设备。cap_add: [SYS_ADMIN]允许挂载文件系统、操作 namespace常被用于逃逸。--pidhost、--nethost共享宿主机 PID/网络命名空间扩大攻击面。挂载/proc、/sys、/dev可能修改内核参数、访问设备。hostPath挂载宿主机/、/etc、/var/run直接读写宿主机敏感目录。在 Kubernetes 中对应的是securityContext.privileged: true、hostPID: true、hostNetwork: true、hostPath卷。Kubernetes 提供了 Pod Security StandardsBaseline、Restricted和 Pod Security Admission 来限制这些配置。生产环境应尽量使用 Restricted 策略至少禁用 privileged、hostPath、hostPID、hostNetwork。修复建议不要挂载 docker.sock如果必须让容器控制 Docker使用 docker-socket-proxy 限制可调用的 API使用非 root 用户运行容器启用 userns-remap在 K8s 中启用 Pod Security Admission并用 OPA/Gatekeeper 或 Kyverno 做策略校验。案例三sudo 通配符与 SUID 提权# /etc/sudoers.d/deploy —— 看似最小授权实则等价于 rootdeployALL(root)NOPASSWD: /usr/bin/find deployALL(root)NOPASSWD: /usr/bin/tar *find带-exec可以直接执行命令tar带--checkpoint-actionexec同样可以。GTFOBins 上收录了上百个这类“合法但危险”的二进制。SUID 同理一个-rwsr-xr-x的自研程序只要内部调用了system()且未清理环境变量就能通过PATH劫持提权。具体利用方式# 查看当前用户的 sudo 权限sudo-l# 如果输出包含 NOPASSWD: /usr/bin/findsudofind/-exec/bin/sh\;-quit# 如果输出包含 NOPASSWD: /usr/bin/tarsudotar-cf/dev/null /dev/null--checkpoint1--checkpoint-actionexec/bin/shGTFOBins 上常见的提权二进制还包括vim、less、awk、perl、python、env、nmap、docker、git、ftp、man、more、nano、rsync、zip、gdb等。只要 sudo 允许其中任意一个并且没有限制参数攻击者就可以借助它执行任意命令。SUID 提权同样常见。查找 SUID 文件find/-perm-4000-typef2/dev/null常见 SUID 程序包括passwd、sudo、ping、mount、umount、pkexecCVE-2021-4034 就是 pkexec 的漏洞但这里讨论的是配置问题。如果存在一个自研 SUID 程序内部调用了system()且未清理环境变量攻击者可以exportPATH/tmp:$PATHecho/bin/sh/tmp/lschmodx /tmp/ls ./suid_program程序调用system(ls)时会优先执行/tmp/ls从而获得 root shell。Capabilities 也是提权入口。查找getcap-r/2/dev/null如果某个程序有cap_setuidep攻击者可以用它设置 UIDpython-cimport os; os.setuid(0); os.system(/bin/sh)修复建议sudo 规则避免通配符使用绝对路径和固定参数必要时用sudoedit或专用包装脚本移除不必要的 SUID用noexec挂载/tmp、/dev/shm限制 Capabilities使用setcap精确授权而不是给二进制全部能力。踩坑与优化建议1. 把配置当成代码来管理手工改配置是配置漂移的根源。用 Ansible / Terraform / Helm 声明式地定义权限、挂载、端口暴露把基线写进 CI 的 lint 环节如kube-score、checkov、kube-linter让危险配置在合并前就被拦下。进一步说IaC 的价值不仅是“自动化”更是“可审计、可回滚、可对比”。每一次配置变更都应该经过代码评审进入 Git 历史。运行时配置应该定期与 Git 仓库中的期望状态对比发现漂移后及时告警。常用的工具包括checkov检查 Terraform、CloudFormation、Kubernetes、Dockerfile 的安全配置。kube-score、kube-linter检查 Kubernetes YAML 的最佳实践。tfsecTerraform 安全扫描。conftest用 OPA/Rego 写自定义策略校验任意结构化配置。lynis主机安全基线审计。例如在 CI 中加入checkov -d .可以提前发现privileged: true、hostPath、docker.sock挂载等危险配置。2. 最小权限要“可验证”而不是“看起来少”“少给权限”是直觉“验证还能做什么”才是工程。定期跑一遍下面这种基线自查比读一遍 sudoers 文件可靠得多#!/usr/bin/env bash# host-baseline-audit.sh —— 服务器配置与权限基线自查set-euopipefailexec(tee-a/var/log/host-baseline-$(date%F).log)21echo 1. SUID/SGID 文件提权入口 find/-xdev\(-perm-4000-o-perm-2000\)-typef\!-path/proc/*!-path/sys/*!-path/snap/*\-printf%m %u:%g %p\n2/dev/null|sortechoecho 2. ![请添加图片描述](https://i-blog.csdnimg.cn/direct/ef91cea023a44cc697774897304d2ce8.gif) ![请添加图片描述](https://i-blog.csdnimg.cn/direct/24421c8fe46a48989d8b65b8c766f5ca.png) ![请添加图片描述](https://i-blog.csdnimg.cn/direct/62f16179494f4cbea4b16419a1ce1749.png) ![请添加图片描述](https://i-blog.csdnimg.cn/direct/2eb37ce349744278b017fad847e052b2.png) ![请添加图片描述](https://i-blog.csdnimg.cn/direct/380ed872401745d8885d0d5dd2b01680.jpeg) **更多硬核网安与AI工具包请扫码获取完整源码** 全局可写且无 sticky 位的目录 find/-xdev-typed-perm-0002!-perm
返回列表