做边界接入设备安全自查这些年我发现一个挺有意思的现象大家聊到远程接入网关的风险第一反应永远是弱口令、未授权访问、反序列化这些听起来就很严重的问题而任意文件读取往往被排在很后面甚至在资产台账的风险评级里只给一个中危。可真到演练复盘的时候偏偏是这类只读的缺陷最后把整条链路串了起来——一个能读文件的口子读到了配置文件配置文件里躺着凭据凭据又能登到别的系统上于是读个文件变成了进了一片区域。这篇内容我想把这条链路完整拆一遍从复现环境怎么在合规前提下搭、这类缺陷的典型成因和定位方法、到后利用阶段的风险推演逻辑最后落到一份能直接拿去用的加固自查表。适合做边界设备运维的同行、做应用安全测试的同学以及负责资产风险评级但不太确定文件读取到底算几级的管理岗参考。1. 先把风险定性搞清楚为什么只读缺陷值得单独写一篇1.1 文件读取缺陷的真实危害边界很多人对任意文件读取的认知停留在能看/etc/passwd觉得里面没有明文口令危害有限。这个判断在十年前勉强成立放到现在明显低估了。现代接入类设备的运行目录里通常有这么几类东西应用配置文件含数据库连接串、缓存地址、第三方接口密钥、证书与私钥文件、会话与令牌的落盘缓存、审计日志、以及升级包和脚本目录。这些东西单看每一项都不算致命但组合起来就是一份相当完整的地形图——你知道它连了哪个数据库、调了哪个认证服务、内部用了什么网段、甚至是哪几个管理员账号在做变更。我的经验是评估这类缺陷时要看三个维度而不是一个可读取的范围能不能穿越目录、能不能读二进制、文件内容的敏感度有没有凭据类信息、读取者的身份门槛匿名可读还是有会话即可。三个维度里只要有两个偏高就应当按高危处理而不是看它只能读不能写就降级。因为攻击链里写往往不是必需的读到的凭据本身就是一条更安静的路径。1.2 从只读缺陷到横向风险的链条拆解把这条链拆开看大概是这样几步第一步确认缺陷存在并能稳定读到已知文件这是验证阶段第二步把读取目标从系统文件转向应用自身的配置与凭证文件这是信息收集阶段第三步从配置里提取出可复用的凭据、密钥或者内部地址这是提权/横向的准备第四步用这些凭据去尝试访问内部其他资源这一步能不能成取决于目标环境的隔离做得好不好。我一直跟团队强调第三、四步的成败不取决于攻击者多厉害而取决于防守方的隔离做得有多细。如果接入设备所在的区域和其他业务区之间只有一条策略宽松的通道如果各系统的运维账号用了同一套口令如果证书私钥和应用配置放在同一个可读目录里那这条链几乎必然走得通。反过来哪怕缺陷存在只要凭证管理是分域的、网络分区是收敛的、账号是独立的伤害就被限制在泄露了一些配置信息这个量级上。所以做加固的时候重点不该只放在堵住那个参数而要放在假设它被读到了损失能有多大。1.3 这篇内容适合谁看怎么用如果你是设备运维方直接跳到第 5 节的加固清单那部分是能当天落地的东西如果你是安全测试人员第 2、3 节讲的是环境搭建和定位思路注意所有操作的前提是书面授权如果你做资产管理或风险评估第 1 节和第 4 节的定性逻辑可以直接拿去做评级依据。第 6 节收集的是我在自查和排障过程中真实踩过的坑比如加固之后业务功能挂了怎么快速定位、哪些现象容易被误判成缺陷。需要提前说清楚一件事这篇内容里所有涉及具体实现的部分都只讲成因与防御不提供可直接用于未授权访问的操作细节。原因很简单这类内容的读者绝大部分是做防守的给出攻击细节的收益远小于风险。真正的复现工作应该在授权靶场或者自有测试环境里做这一点我在下一节会展开。2. 复现环境的搭建思路与合规边界2.1 三条必须先立住的规则在动手之前我给自己团队定了三条铁律任何人做这类验证都必须满足。第一书面授权先行授权文件里要写清楚测试的目标范围IP、域名、时间段、测试类型、以及紧急联系人和中止条件。口头同意、领导说可以这类都不算因为一旦影响到生产责任无法界定。第二只在隔离环境复现用自己搭的靶场或者厂商提供的测试镜像绝不拿生产设备当试验田。第三数据不外带验证过程中如果读到了真实业务数据截图要脱敏样本要及时清理不要存到个人电脑上。这三条听起来像老生常谈但我见过太多我就试一下最后变成事故的案例。特别是接入类设备它往往处在边界位置一旦验证过程中触发了保护机制把设备锁死或者重启影响的是整片区域的接入恢复成本极高。2.2 靶场拓扑怎么搭才贴近真实靶场不需要复杂但要保留关键的结构特征。我一般搭三层最外层是一台模拟的边界接入设备用测试版镜像或者干脆用一个自己写的带文件读取接口的 Demo 服务来模拟同类逻辑中间一层是模拟的内部应用区放一两个 Web 服务和一台数据库最内层放一台敏感数据机用来验证横向能走多远。三层之间用防火墙策略隔开策略要故意做成真实环境里常见的那种粗糙配置——比如允许某几个端口全通因为你要验证的正是粗糙配置会放大多少伤害。这个拓扑的价值在于它能把读文件和横向之间的因果关系量化出来。你可以先按严格隔离跑一遍记录攻击链能走几步再把策略放宽一档再跑一遍。两次结果的差异就是隔离策略的实际价值这个数据拿去做加固立项的说服力比任何理论描述都强。我做过一次这样的对比严格隔离的情况下从文件读取到触达第二个系统之间隔了差不多四道门槛而宽松配置下只剩一道这个差距在评审会上非常有冲击力。2.3 抓包与验证工具的最小化配置工具选择上我倾向于够用就行不要堆一堆插件。基础的抓包代理 一个能改请求的重放工具 一份自己维护的请求清单基本就覆盖了验证需求。配置上有几个细节值得注意代理要关掉对静态资源的拦截只保留对动态接口的抓取否则请求列表会被图片和脚本淹没重放工具里要把目标域名固定在靶场地址上避免误发到真实站点如果是 HTTPS测试环境的证书要单独签发不要用生产证书。还有一点是很多人忽略的记录要同步做。验证过程中每一步的请求、响应、时间戳都要落到文档里不要指望事后回忆。我做复现记录的习惯是开一个 Markdown 文件按时间 - 请求特征 - 响应特征 - 判断四列记最后这份记录直接就是报告的素材。等到写报告的时候再回头翻抓包文件效率会低很多。3. 文件读取类缺陷的常见成因与定位方法3.1 参数进入文件路径的几种典型写法归根到底这类缺陷的成因只有一个用户可控的输入被拼进了文件路径。但具体到代码里写法五花八门。最常见的是文件名直接拼接比如下载接口接收一个 name 参数拼上固定的目录前缀就去读稍微隐蔽一点的是模板路径拼接比如错误页、皮肤、语言包这类功能路径由参数决定再隐蔽的是间接拼接参数先进了一个映射表映射表里的值再拼进路径这种在静态扫描里很容易漏掉。我在自查时用的是一个笨办法但很有效把应用里所有涉及File、open、read、InputStream、Paths.get这类调用的位置列出来然后逐个往上追参数来源看有没有经过 HTTP 层。这个工作量比想象中小一个中等规模的应用通常也就几十处。追的时候重点看三类入口文件下载/预览、日志查看、导入导出。这三类功能几乎必然涉及路径拼接是缺陷的高发区。3.2 白名单和路径规范化做了但没做对的坑很多代码里其实是有防护的问题在于防护写得不彻底。我总结了几种典型的伪防护防护写法表面效果实际问题过滤../字符串挡住常规穿越编码变形、多重斜杠、绝对路径绕过只校验开头是否等于基目录看起来限制了范围拼接顺序错误或未做规范化时失效校验后直接用原始字符串读文件校验和读的是两个东西校验与使用之间存在不一致用正则黑名单拦关键字拦住了已知模式黑名单永远补不完且易误伤正常文件名限制文件后缀缩小了范围后缀不决定内容且可读的敏感文件未必有后缀核心问题在于校验的对象和实际读取的对象必须是同一个规范化之后的绝对路径。正确做法是先把用户输入解析成绝对路径并做规范化处理消除..、多余分隔符、符号链接然后判断这个规范化后的路径是否落在允许的基目录之下最后用这个规范化后的路径去读。顺序错了、对象错了防护就形同虚设。下面是我在一个自查项目里用的校验逻辑示意语言用的是 Java思路可以直接搬到其他语言// 关键点先规范化再判断前缀最后用规范化后的路径读取 public Path resolveSafely(Path baseDir, String userInput) throws IOException { // 1. 把基目录也规范化成真实路径避免符号链接造成的前缀误判 Path base baseDir.toRealPath(); // 2. 解析用户输入注意 resolve 会保留 ..必须再 normalize Path target base.resolve(userInput).normalize(); // 3. 用规范化后的路径做前缀判断要求带分隔符避免 /data/abc 匹配到 /data/abcd if (!target.startsWith(base File.separator)) { throw new SecurityException(path out of base dir); } // 4. 处理符号链接如果目标已存在取真实路径再判一次 if (Files.exists(target)) { Path real target.toRealPath(); if (!real.startsWith(base File.separator)) { throw new SecurityException(symlink escape); } return real; } return target; }这段代码里有三个容易被忽略的点startsWith必须带分隔符否则前缀匹配会误放行符号链接要单独处理因为规范化不解决链接指向的问题toRealPath要求路径存在所以对不存在的文件要单独分支。3.3 从响应特征判断是否真的读到了文件验证阶段最怕的是以为读到了其实没读到。判断依据主要看三点响应长度是否随目标文件变化、响应内容是否符合该文件类型的特征比如配置文件有明显的键值结构二进制文件有固定的头部魔数、错误信息是否泄露了路径信息。第三点特别值得注意很多应用在文件不存在时会返回包含完整绝对路径的异常栈这本身就是一个信息泄露问题即使读取没成功也说明错误处理需要整改。我一般会准备一组对照文件一个已知内容的文本文件、一个不存在的路径、一个目录路径。三次请求的响应差异能很清楚地说明问题——如果文本文件返回了预期内容不存在路径返回了通用错误目录路径返回了列表或者权限错误基本可以确认读取能力是真实的。如果三次响应完全一样比如都是同一个错误页那大概率是中间有网关拦截或者应用做了统一处理需要换个思路。4. 后利用风险推演为什么会引出横向移动4.1 配置文件里的高价值信息盘点从防御视角看最该关心的是攻击者读到什么会让我们最难受。我按危害程度给常见的文件类型排了个序第一档凭据类。数据库连接串里的账号口令、第三方接口的 AppKey/AppSecret、缓存与消息队列的认证信息、云服务的访问密钥。这些一旦泄露攻击者不需要再找漏洞直接用合法凭据登录即可日志里看起来和正常运维没区别。第二档密钥与证书类。TLS 私钥、签名私钥、CA 证书链。私钥泄露意味着可以伪造服务这在中间人场景里是毁灭性的。第三档拓扑与配置类。内部服务地址、网段规划、路由配置、上游依赖清单。这些本身不直接可用但能大幅降低攻击者的探测成本。第四档业务数据与日志。用户信息、审计记录。危害直接但通常范围有限。很多单位在做加固时把重点全放在堵住读取入口却忽略了即使被读到也不该这么值钱。我的观点是后者更重要因为它是一次性的架构改进而前者需要持续对抗。4.2 凭据复用与网络分段的博弈横向能不能走通本质上是两个因素的乘积凭据的复用程度 × 网络的连通程度。任何一项趋近于零整体风险就趋近于零。所以加固有两条完全独立的路径两条都做是最稳的。凭据这条路上最有效的措施是一系统一口令 定期轮换 不落明文。我在自查时见过最糟的情况是接入设备、堡垒机、数据库、监控系统用了同一个运维账号口令还写在配置文件里。这种情况下读到一个文件等于拿到半个环境。改进的做法是引入统一的凭据管理配置文件里只放引用标识实际口令由运行时从凭据服务拉取且每个服务一个独立身份。网络这条路上核心是分区收敛 默认拒绝。接入设备所在的区域应该被当成半信任区它对内网的访问必须逐条放行而不是逐条拒绝。这里有个实操细节很多策略是历史遗留的一条条加出来的没人敢删。我建议做一次全量梳理把每条策略的用途、责任人、最后命中时间都列出来超过半年没命中的直接标记待清理。这个过程通常能砍掉三到五成的冗余策略。4.3 日志视角哪些行为会留下痕迹后利用阶段最怕的是无声。所以防守方的目标不是阻止一切而是让每一步都留下痕迹。文件读取类行为在日志上有几个特征值得关注短时间内对同一接口的大量请求、参数里出现路径分隔符或编码变形、请求的文件名集中在配置类文件上、来自同一源 IP 的请求在成功读取后突然转向其他服务。这里要提醒一点应用日志和系统日志要对得上。很多时候应用层记录了请求但文件系统层的实际访问没有记录导致无法确认到底读没读到。建议在敏感目录上开启文件访问审计把读操作也记下来虽然量会大一些但出事时这份日志的价值无可替代。5. 加固落地一份可以照着做的自查表5.1 应用侧把路径校验做扎实应用侧的目标很明确任何由外部输入决定的文件路径都必须经过规范化 白名单校验。具体落地有四个动作。第一把文件访问的入口收敛理想状态是全应用只有一个统一的文件读取工具类所有功能都走它这样审计面就只有一个点。第二白名单要用允许的目录 允许的文件名模式双重限制而不是只判断前缀。第三禁止把用户输入直接当路径用需要的话维护一张标识 → 真实路径的映射表对外只暴露标识。第四错误处理统一化任何文件相关的异常都返回通用提示绝不把路径、堆栈、系统信息带出去。第四点经常被当成不影响功能而排在最后实际上它的优先级很高。因为路径泄露本身就是信息收集的起点攻击者拿到完整路径后后续的猜测成本会大幅降低。# 系统侧加固示例敏感目录收紧权限服务账户降权 # 假设应用以 appsvc 用户运行配置目录为 /opt/gateway/conf # 1. 目录属主给 root应用账户只读不可写 chown -R root:root /opt/gateway/conf chmod -R 750 /opt/gateway/conf # 2. 配置文件里含凭据的部分单独隔离仅允许特定组读取 chgrp credgrp /opt/gateway/conf/secret.properties chmod 640 /opt/gateway/conf/secret.properties # 3. 应用运行账户加入该组但不给 shell usermod -aG credgrp appsvc usermod -s /usr/sbin/nologin appsvc # 4. 设置 umask防止新生成文件默认过宽 echo umask 027 /etc/profile5.2 系统侧让服务账户低到尘埃里接入类设备有个通病服务进程以高权限运行理由是方便操作硬件和网络配置。这在安全上是灾难性的因为一旦应用层被突破攻击者直接继承高权限。改进路径是拆分进程权限负责监听和协议处理的主进程降权运行只有确实需要高权限的操作比如绑定低端口、修改网络配置通过一个独立的、接口极窄的辅助进程来做两者之间用受控的本地通道通信。权限收敛之外还要注意文件系统的层次。我的建议是把运行目录分成三块只读的程序目录属主 root应用只读、可写的运行数据目录属主应用账户权限 700、以及独立的凭据目录属主 root应用通过特定组读。三块之间不交叉这样即使应用被拿下能改的也只有数据目录程序本身和凭据都不会被直接篡改。注意降权之前一定要把应用的写路径全部梳理一遍。我踩过一次坑降权之后应用起不来排查半天发现是它在启动时会往程序目录写一个临时锁文件。这类隐藏的写操作只能靠实际跑一遍才能发现光看文档是看不出来的。5.3 运维侧暴露面收敛与补丁节奏运维侧的三件事少暴露、快打补丁、勤换口令。暴露面这块接入设备的管理的接口不应该对全网开放应该限制在运维网段且最好再加一层跳板。很多单位的管理口和业务口在同一个地址上只是路径不同这种情况下只要业务口对外开放管理口就跟着暴露了这是很常见的架构问题。补丁节奏上我建议对边界类设备建立单独的台账记录当前版本、厂商公告、已知问题、上次升级时间。升级窗口要提前和业务方对齐因为接入设备重启影响面大。这里有个现实问题有些历史版本升级路径很长需要逐级升不能直接跳。所以台账里最好把升级路径也记下来免得到时候手忙脚乱。口令轮换这件事最容易流于形式。我的做法是把所有设备的运维账号纳入统一管理设置强口令策略和 90 天轮换同时对服务间使用的凭据单独管理不走人工轮换而是走自动签发。人工轮换的凭据越多越容易出现在配置文件里这是个恶性循环。5.4 监测侧几条能直接配的告警规则监测规则不需要多关键是要准。我一般会给接入设备配这么几条规则触发条件关注理由路径穿越特征请求参数含..、编码后的点号、多重分隔符直接对应缺陷利用敏感文件探测请求中出现配置类、密钥类文件名说明在定向收集短时高频读同一源 5 分钟内对文件类接口超过 30 次典型的批量探测行为异常时段访问非工作时段的管理口登录合法凭据被盗用的信号跨区访问突增接入设备所在区对其他区的连接数突增横向移动的前兆规则配好之后一定要做误报调优。比如短时高频读这条正常的批量下载业务很容易触发所以阈值要结合业务基线来定或者加上目标文件属于敏感目录的联合条件。我见过太多规则配完就没人管的例子最后告警列表全是噪音真出事的时候反而被淹没了。6. 常见问题与排查实录6.1 几种容易被误判的情况自查过程中最容易出的一种误判是把正常的文件下载接口当成缺陷。区别在于正常的下载接口用户输入的是一个标识ID、哈希、文件名服务端通过标识去映射真实路径而缺陷接口用户输入直接参与路径构造。判断方法是往参数里塞一个明显的路径特征如果行为发生变化比如报错信息里出现路径、返回内容变成另一个文件才说明输入真的影响了路径。只是返回 404 或者参数错误说明映射机制在工作。第二种误判是编码问题导致的假阳性。有些接口对参数做了 URL 解码你传的编码字符被解成了普通字符看起来像是绕过了过滤实际上是应用正常处理。这种情况要多试几种编码层级对比响应差异别急着下结论。第三种是网关拦截造成的假阴性。应用层明明有缺陷但前面的网关把带特殊字符的请求全拦了测试时看到的都是统一错误页。这种情况需要用白名单内的正常请求做对照确认请求确实到达了应用层否则你测的其实是网关。6.2 加固之后功能异常按这个顺序查加固上线后功能出问题排查顺序我一般是这样先看应用日志里的异常类型是权限拒绝还是文件不存在这两者的方向完全不同如果是权限拒绝用服务账户身份手动执行一次读操作确认是文件权限问题还是目录权限问题目录没有执行权限时即使文件可读也打不开这点经常被忽略如果是文件不存在检查是不是规范化之后路径变了比如软链接被解析到了别的目录。还有一个隐蔽的坑加固时把umask改了导致应用生成的临时文件权限变了其他进程读不到。这类问题在单机测试时完全正常一到集群环境就暴露出来因为另一台机器上的进程用的是不同的账户。所以加固方案一定要在贴近生产的集群环境里验证一遍别只在单机上跑通就上线。6.3 一份快速排查对照表现象可能原因处理方向加固后下载功能 403白名单目录配置遗漏核对允许目录清单补上业务实际路径读取正常但内容为空规范化后指向了空文件或链接目标打印规范化前后的路径对比加密配置读不出来服务账户不在凭据组内检查组成员关系注意需重新登录生效日志里大量路径告警但业务正常业务本身含路径参数属误报加白名单或改联合条件别直接关规则集群中部分节点失败各节点目录结构或账户不一致用配置管理工具统一基线逐节点校验升级后配置丢失升级脚本覆盖了自定义配置升级前备份升级后比对差异最后分享一个我自己一直在用的小习惯每次做完这类自查我都会把这次读到了什么整理成一份内部通报不是通报漏洞而是通报我们的配置文件里到底放了多少不该放的东西。这份通报往往比漏洞报告更能推动改进因为它让业务方直观看到一个看似不起眼的读取缺陷可能牵出多少本该被隔离的信息。做过两三轮之后配置文件里的明文凭据会明显减少这比任何一次性的补丁都管用。
阅读完成 · 觉得有帮助?