尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

目录遍历、越权与信息泄露:原理、排查与修复实战指南

目录遍历、越权与信息泄露:原理、排查与修复实战指南 目录遍历、越权、信息泄露这三类漏洞放在一起讲其实挺有讲究的。我在做安全测试和应急响应的这些年里遇到过太多因为这三类问题翻车的项目小到个人博客被挂马大到核心业务数据库被拖走源头往往就是其中某一个看起来技术含量不高的隐患。不过有意思的是它们虽然成因不同、表现各异却经常在同一个系统里同时出现而且都指向同一件事对用户输入和访问边界的信任过了头。这篇文章我打算按目录遍历、越权、信息泄露的顺序逐个拆开讲清楚它们的原理、高发场景、排查思路和修复方法也会结合像 sa-token 横纵越权、Spring Boot heapdump 敏感信息泄露、SSL/TLS 弱加密算法这类近期比较热的问题聊聊我在实际项目中踩过的坑和验证过的做法。内容主要面向做开发、测试、运维以及刚转安全的朋友老手也可以重点看看越权自查方案和漏洞优先级排序那部分。1. 目录遍历漏洞老掉牙却反复出现的高危问题1.1 目录遍历的原理到底是什么目录遍历漏洞英文一般叫 Directory Traversal 或 Path Traversal本质上是攻击者通过输入特殊构造的路径序列让服务器跳出原本限定的目录范围去读取或操作其他文件。最常见的输入就是../这种相对路径跳转符配合文件名就能拼出像../../../../etc/passwd这样的路径。服务器端接收参数后如果直接把这个值拼接到文件路径里用file_get_contents、Files.readAllBytes、sendFile这类函数去读取文件或者用Runtime.exec、ProcessBuilder去执行命令就会出问题。你传入一个../操作系统就往上跳一级连续跳几次就跳出网站根目录了。听起来很简单但它变种很多。比如在 URL 里直接传..%2f即../的 URL 编码形式或者用双重编码..%252f还有用绝对路径/etc/passwd直接读取、用....//绕过简单过滤等等。我在测试中见过不少开发者对../做了字符串替换但如果只把../替换成空字符串攻击者构造....//时替换掉中间的../后反而留下../照样能穿目录。这类过滤绕过问题是目录遍历漏洞排查中绕不开的一环。1.2 为什么它在这么多年后依然高频出现你可能会想这种漏洞十年前就有了怎么现在还这么普遍。实际排查下来的原因主要有三个。第一个是文件下载、文件预览、导出报表这类功能天生就容易踩坑。只要有根据用户传入文件名去服务器上取文件这种逻辑就存在目录遍历的风险。比如一个导出 Excel 的功能前端传fileNamexxx.xlsx后端直接拼接路径去读文件攻击者把参数改成../../config/db.properties敏感配置就出去了。我扫过的很多系统这类问题往往集中在文件下载接口、图片预览接口、模板加载接口上。第二个是过滤逻辑不严谨。很多团队的防御方式是过滤掉..而不是校验最终路径是否在允许范围内。前者只要存在编码变体、嵌套绕过等方式就很容易失守后者才是相对稳妥的思路。比如先对路径做规范化canonicalization再检查规范化后结果是否以允许目录前缀开头这才是有效做法。第三个是测试覆盖不足。开发自测时一般只验证正常路径比如传个合法文件名能正常下载很少有人主动传../../去试异常场景。这个问题在接口文档里通常也写不清楚哪些参数是文件路径、哪些目录是允许访问的等安全测试提出来往往功能已经上线了。1.3 目录遍历的检测方法和修复方案先说检测。在没有专业扫描器的情况下我常用的方法是先用接口文档或者抓包把涉及文件操作的接口全部找出来重点看参数名里带 fileName、filePath、path、url、template 的。然后直接修改参数值在正常文件名的前面或中间插入../序列观察响应内容变化。一个很有效的测试思路是先请求一个不存在的文件名比如abc_does_not_exist.txt看报错信息是否暴露了物理路径再请求../../../../etc/passwd在 Linux 环境下一旦响应里出现root:x:0:0:之类的行基本就确认了。Windows 环境可以试..\..\..\..\windows\win.ini。需要说明一点所有测试都必须在你自己授权范围内进行别拿这套方法去碰不属于你的系统这是行业底线。修复方面我给开发团队推荐过一套相对完整的方案按优先级排序首选方案是白名单校验。如果业务允许访问的文件是有限的直接用白名单映射前端传文件 ID 而不是路径后端在 Map 里找对应文件名这种方法最安全因为攻击者根本没有机会传路径进来。如果必须支持动态文件名那就要对用户输入做严格校验。拒绝所有包含..、/、\、空字节的输入同时做 URL 解码后再校验避免编码绕过。在 Java 里可以用Paths.get(baseDir, userInput).normalize()得到规范化路径再用startsWith(baseDir)判断是否越界在 Python 里类似用os.path.realpath()取真实路径后判断。这套逻辑已经能堵住大部分问题。底线上要把应用进程权限降下来让 Web 服务只能访问网站目录和必要的读写目录即使被穿越也拿不到系统关键文件。2. 越权漏洞水平越权与垂直越权全面拆解2.1 水平越权和垂直越权到底怎么区分越权漏洞也叫访问控制漏洞是目前业务逻辑漏洞里最头疼的一类。它分两种水平越权和垂直越权。很多同行管它们叫横向越权和纵向越权意思一样只是叫法不同。水平越权简单说就是同级用户之间越权访问。两个用户都是普通用户A 用户通过修改请求中的用户 ID、订单号、发票号这类资源标识就能读取、修改 B 用户的私有数据。比如一个查看订单详情的接口URL 是/order/detail?orderId10001后端不加校验直接按这个 ID 查询并返回那我把 10001 改成 10002就能看到别人的订单了。典型场景包括查看他人订单、修改他人个人信息、操作他人购物车、查看他人简历、查看他人私聊记录等。垂直越权则是低权限用户访问高权限功能。普通用户直接请求管理员接口或者普通员工调用 HR 系统里只有 HR 才能用的接口都属于垂直越权。它的判断标准不是能不能登录而是登录后能不能调用超出自己角色权限的接口。常见的表现有前端把按钮隐藏了但后端没做权限校验攻击者直接模拟 HTTP 请求就能访问管理员功能。这两个概念经常被放在一起讨论是因为它们常常同时出现在一个系统里某些接口既没校验资源是否属于当前用户水平也没校验当前角色是否有权访问垂直那就是双重越权。这也是为什么最近横纵越权这个词会火起来很多安全公告里直接用横纵越权来描述一个系统同时存在水平越权和垂直越权的情况。2.2 越权漏洞为什么是逻辑漏洞之王越权漏洞之所以危险不是因为技术难度高而是因为它极其隐蔽且杀伤力极大。SQL 注入、RCE 这类漏洞靠扫描器就能发现一大堆但越权漏洞必须理解业务逻辑才能识别。很多自动化扫描器根本不知道这个订单 ID 应该是属于当前用户的它只看响应状态码和内容所以漏报率很高。我从经验来看越权漏洞的高发位置集中在以下几类接口根据 ID 查询详情类的接口。比如订单详情、用户详情、消息详情这类接口天生以 ID 为参数最容易出现水平越权。开发人员往往默认别人不可能猜到 ID但 ID 通常是自增数字猜到只是时间问题。状态变更类的接口。比如订单改价、用户禁用、退款审批、文章删除这类接口一旦缺少角色校验就会出现普通用户修改管理数据的垂直越权。批量导出和列表查询。很多列表接口支持传 userId、deptId 来筛选数据如果当前用户的身份不是从 Session/Token 里取而是从请求参数里取那直接把参数改成别人的 ID 就能导出别人的数据。文件上传和下载。上传接口如果不校验文件归属可能 A 用户上传的文件可以被 B 用户覆盖或删除。越权漏洞修复的难点还在于它的根因是缺少统一的鉴权模型。业务接口多、权限规则复杂每个接口单独判断就容易漏。很多项目前期没做权限设计后补的话改动量巨大这也是为什么很多系统存在大量越权问题却迟迟不修。2.3 结合 sa-token 谈横纵越权的成因与防护说到 Java 后端的越权防护sa-token 是现在比较流行的鉴权框架在前后端分离的项目里用得很多。它有登录认证、权限认证、SSO、OAuth2 等功能本身设计是没什么问题的但我在实际排查中见过不少因为用法不对导致的越权。最常见的一种错误是只配置了登录认证拦截器确保没登录不能访问但没做权限认证意味着只要是登录用户不管什么角色都能访问所有接口。比如一个后台管理接口只加了StpUtil.checkLogin()来验证是否登录但没校验当前用户是不是管理员普通用户登录后直接请求这个接口一样能通。这就是典型的垂直越权而且是横纵越权里最常见的一种成因。另一种错误是获取当前用户 ID 的方式不对。有些代码里写Long userId Long.parseLong(request.getParameter(userId))从请求参数拿用户 ID然后拿这个 ID 去查询用户数据。这样就完全绕过了权限体系攻击者想查谁就查谁水平越权就来了。正确做法应该是从当前登录状态里取sa-token 里通常用StpUtil.getLoginId()拿到当前会话对应的用户 ID然后校验这个用户是否有权限访问目标资源。还有一种容易忽略的场景sa-token 的权限认证依赖权限码或角色码需要在登录时给用户赋予对应的权限。如果权限码本身设计得粗糙比如所有普通用户都拥有一个写死的admin:all权限那权限校验形同虚设。务实点讲做权限设计时应该遵循最小权限原则按角色拆分权限码并且要区分数据级权限和功能级权限。sa-token 能做功能级权限校验但数据级权限比如只能看本部门的订单需要业务层自行判断很多越权漏洞恰恰发生在数据级权限缺失上。2.4 一套可落地的越权自查方案先说结论越权漏洞的测试基础是接口级黑盒 业务理解纯跑扫描器基本没用。我自己的自查流程大致如下。第一步梳理所有涉及资源 ID的接口。把接口文档导出来逐个标出哪些参数是资源标识如 ID、编号、单号这个清单就是测试范围。没有接口文档的项目可以通过抓包把所有 API 过一遍重点找 restful 风格的接口。第二步准备两个测试账号。水平越权测试必须要有两个同级账号比如 userA 和 userB。用 userA 登录拿到自己某个资源的 ID再换 userB 的 Token 去请求 userA 的资源 ID如果成功返回数据就说明存在水平越权。这里有个实用技巧不要只测一个接口要批量遍历 ID 范围很多系统单个越权和可遍历多个 ID的危害等级完全不同。第三步测试垂直越权。准备一个普通用户账号和一个管理员账号先拿管理员请求一个管理接口的完整请求包把 Token 换成普通用户的 Token再发送一次看是否仍有权限。如果返回 200 且包含管理数据就是垂直越权。修复层面我给开发同学的建议是所有涉及用户私有数据的接口都必须做资源归属校验判断当前登录用户 ID 是否等于资源所属用户 ID所有管理功能接口必须做角色/权限校验仅校验登录状态远远不够。如果有条件把两类校验抽象成公共注解或统一拦截器避免每个接口各写一套。另外接口返回数据时也要注意不要泄露不该返回的字段比如用户表里如果存了手机号、身份证号列表接口默认就别返回要用的时候单独查。3. 信息泄露漏洞敏感数据是怎么悄悄流出去的3.1 信息泄露的常见类型信息泄露漏洞是个大筐只要是敏感数据暴露给了不该看到的人都能算这一类。从我在实际项目里遇到的案例来看比较高频的有下面几种。第一种是目录/文件泄露。比如网站根目录下存在.git目录通过工具就能把源码历史记录拉下来又比如允许目录浏览访问某个路径直接列出所有文件名。我曾经在一个客户的项目里发现/backup/目录可以直接浏览里面躺着一份三个月前的数据库备份下载下来解压就能看到明文密码。这种情况在开发环境变成生产环境时特别常见备份脚本只改了路径没改访问权限。第二种是错误信息和版本信息泄露。页面报错时直接输出堆栈、SQL 语句、物理路径攻击者根据报错信息能判断出用了什么框架、什么数据库、什么版本针对性找漏洞就容易多了。比如日志里打出org.springframework.jdbc的包名基本能确认是 Spring Boot JDBC再比如某些框架的默认报错页会直接显示框架版本拿到版本号就能去查这个版本有哪些已知漏洞。第三种是接口/配置信息泄露。Swagger/OpenAPI 文档暴露在公网把系统所有接口定义、参数模型全都看光了Actuator 监控端点暴露/actuator/env、/actuator/health把环境变量、配置项漏了出来还有前端打包时候注释没清源码里带着内网 IP、数据库地址、第三方平台密钥。这类问题防不胜防我在很多前端 JS 文件里都挖到过硬编码的密钥。第四种是第三方服务的信息泄露。比如把阿里云 AccessKey 写死在代码或配置里然后被拖进公开仓库再比如对象存储桶权限配置错误变成公共读任何人都能列出并下载桶内所有文件。这类泄露通常影响范围极大因为云厂商的 AccessKey 往往关联着大量资源和费用。3.2 Spring Boot heapdump 敏感信息泄露近期Spring Boot heapdump 敏感信息泄露这个话题热度不低我也借这个机会展开说说。heapdump 是 Java 虚拟机把当前堆内存快照导出的文件里面包含了进程内存中的所有对象。正常来说这是故障定位时用来分析内存溢出的工具但如果暴露到公网问题就大了。为什么说 heapdump 泄露很致命因为应用运行期间内存里存着大量敏感数据当前登录用户的会话 Token、数据库连接串可能带明文密码、第三方服务密钥、还在内存里未被序列化的业务数据。我在一次应急响应中客户怀疑系统被人提权了排查后才发现对方先下载了/actuator/heapdump文件用工具解析出内存里的数据库账号密码然后直连数据库拖库。整个过程不需要任何高深技巧因为 Spring Boot 的 heapdump 是个固定路径只要端口暴露任何人都能下载。排查和修复思路也很直接。第一检查 Spring Boot 配置把 Actuator 的端点限制在内网或干脆关闭。生产环境至少要把/actuator/heapdump、/actuator/env、/actuator/configprops、/actuator/mappings这类高危端点禁掉。第二如果业务确实需要 Actuator 做监控务必通过独立的监控端口和管理网络访问不要和业务端口混在一起。第三定期用扫描器检查对外暴露的端点很多安全团队开漏洞扫描时默认会探这些路径。另外关于 heapdump 的确认常见工具性办法是用 JVM 的jhat或商业工具去解析但普通开发人员不用深入关键是确认生产环境根本没有这个文件可下载。3.3 SSL/TLS 信息泄露漏洞SSL/TLS 相关的信息泄露漏洞近期被反复提及的是 CVE-2016-2183也就是 SWEET32 攻击所涉及的弱加密算法问题。这个编号听起来很陌生但原理其实不复杂如果服务器配置了 3DES三重数据加密标准或 DES 这类分组加密算法作为 SSL/TLS 的加密套件加密强度相对不足在特定条件下可能被破解会话数据。很多漏洞扫描器报告SSL/TLS 信息泄露漏洞 (CVE-2016-2183)【原理扫描】就是检测到服务器支持的加密套件里包含这类弱算法。这类问题在老旧服务器上特别常见。原因也很现实服务器操作系统和 OpenSSL/Nginx/Apache 版本陈旧默认配置里还带着 3DES。我处理过一个案例一台跑着重要内部系统的服务器扫描报告里报了 CVE-2016-2183但信息部门担心禁用 3DES 会影响老旧浏览器访问迟迟不敢动。后来查了一下连接日志发现实际客户端都是现代浏览器根本不依赖 3DES最后把旧版本升级、弱加密套件禁用扫描就干净了。修复方法是分层的在 TLS 配置层面禁用弱加密套件比如 Nginx 里修改ssl_ciphers配置去掉包含3DES、DES的套件更根本的是升级 OpenSSL 库和服务器系统让底层不再支持过时的协议和算法。另外我一直建议大家把 SSL/TLS 的安全基线检查纳入例行运维每季度扫一次而不是等到漏洞报告出来了才处理。3.4 信息泄露漏洞的排查与修复思路信息泄露和前面两类漏洞不同它很少是单个接口的问题更多是配置和管理的问题。所以排查时我通常不是盯着接口一个个测而是按资产维度来做。我建议的顺序是先盘点对外暴露的资产把所有公网域名、IP、端口列出来不看不知道很多客户盘完才发现自己有十几个早就忘了的测试环境还挂在公网上。然后从四个方面自查一是目录浏览和备份文件用路径字典配合扫描器扫常见目录比如/backup、/git、/web.config、/application.properties二是错误的报错信息直接访问几个不存在的用户 ID看报错内容是否会返回堆栈和 SQL三是开发框架的默认端点像 Spring Boot 的 actuator、Django 的 admin、phpMyAdmin 之类四是前端源码把 JS、CSS 文件下载下来搜里头的 key、token、password、api.xxx.com 这些关键字。修复层面核心原则是最小暴露。敏感接口能放内网就放内网必须公网访问的要做访问控制和身份认证。文件上传和备份目录禁止脚本执行权限web 根目录禁止目录浏览。框架的调试模式、默认控制台、监控端点在生产环境一律关闭。还有一个很实用的小技巧把应用运行账号改成普通权限用户即使被拿到 shell也做不了太多破坏。4. 常见问题与排查技巧实录4.1 三类漏洞的优先修复顺序怎么定在实际工作中团队经常问我的问题是这三类漏洞同时存在先修哪个我的排序思路是垂直越权 目录遍历 水平越权 信息泄露但具体要看数据敏感度和暴露情况。垂直越权排第一是因为普通用户直接打管理员接口影响的往往是全量数据一旦被利用整库都可能丢危害面最大。目录遍历排第二是因为它通常直接读服务器文件容易拿到配置和密码。水平越权排第三是因为它一般只能影响单个用户或小范围数据虽然也很严重但对比前面两个影响面相对可控。信息泄露排最后不是说不重要而是它更多是攻击前的侦察帮助真正被单独利用造成严重破坏的情况相对少但它会放大前两类漏洞的破坏力。比如 heapdump 泄露了数据库密码再配合目录遍历去找配置文件上下攻击链就起来了所以暂时排名靠后但一定不能不管。还有一个务实的建议修复前先把所有公网入口先封一遍。比如把 actuator 端点全部禁用、把备份目录加访问认证这些改动小、见效快能在开发团队排期修复大功能之前先把最明显的风险面收掉。4.2 误报确认如何判断一个告警是不是真漏洞安全扫描器经常会报一堆误报尤其像 CVE-2016-2183 这种原理扫描类问题报出来不代表一定能被利用但是也别直接忽略。我自己判断误报的套路大致是这样。如果是目录遍历类告警扫描器说某个参数存在路径遍历我会手动验证一下构造一个无害的测试路径比如请求一个../../../../tmp/test_probe_2024.txt这种不存在的文件如果返回 404说明服务器确实按这个路径去找文件了但没有读到内容这时再尝试读取存在的文件确认。如果返回结果把路径原样返回但并不去读文件很可能是扫描器根据响应内容误判。如果是越权类告警扫描器基本不会报因为自动扫描器很难理解业务。所以更多情况是开发不承认接口测出来能拿到别人的数据开发说这是正常的用户本来就能查看文章。这时关键是要看数据是否私有。一条订单、一封私信、一份简历属于资源所有者个人那这类访问就是越权一篇文章、一条公告是公共资源那看到就正常。判断标准就是这么朴素。如果是信息泄露类告警比如 Actuator 端点直接访问确认即可。参数值、响应内容、敏感字段都对应得上基本就是实锤。唯一要注意的是有些系统在同一域名下挂了多个应用扫描器报的路径可能在某个静态资源目录里压根不存在这种直接去 URL 访问一下就能排掉。4.3 我的几点实操心得说了这么多最后分享几个从项目里总结出来的实操体会希望对大家有实际参考价值。第一越权漏洞的测试必须懂业务。我曾经花了一下午时间测一个 CRM 系统的导出接口参数是customerId用两个账号测了半天都显示无权访问后来仔细看接口文档才发现系统本身的业务规则就是销售只能导出自己名下的客户所以返回无权访问反而是正常现象。真正的越权点是市场部角色可以导出全公司客户这必须有业务常识才能判断。所以做安全测试不要只盯着技术一定要先了解业务流程。第二修复目录遍历时永远不要只做输入过滤。输入过滤是必要的但只过滤../很容易被绕过。我见过最稳的做法是在代码里对路径做两次解析先 URL 解码再做路径规范化然后用startsWith检查最终路径是否在允许目录内。这套逻辑写成公共函数所有文件操作统一调用比每个接口各写一遍判断要靠谱得多。第三如果是团队协作建议把这三类漏洞的测试用例沉淀成一份 checklist。目录遍历测什么参数、越权测哪些接口、信息泄露看哪些端点写成文档放进 CI/CD 流程里每次发版前自动跑一遍。安全不只是安全团队的事开发自测阶段能拦掉 80% 的低级问题后面整个团队都会轻松很多。我自己带过的项目里凡是坚持做这一件事的上线后漏报率明显低于其他项目。我在实际工作中还有一个体会这三类漏洞的修复方案本身都不复杂难的是发现和坚持。很多团队的问题不是不会修而是根本没有定期测、上线不检查等到出事才匆匆忙忙处理。如果能把安全检测从应急动作变成例行动作很多风险根本走不到生产环境。
返回列表