目录遍历、越权与信息泄露:Web安全三大基础漏洞的原理与实战防护 1. 先从三个词说起目录遍历、越权、信息泄露到底在说什么做安全这块时间久了你会发现一个规律真正让企业头疼的往往不是那些听起来很高深的漏洞类型反而是目录遍历、越权、信息泄露这类基础题。它们不像反序列化、堆溢出那样需要复杂的利用链但危害一点都不小而且特别容易在开发、测试、上线过程中被忽略。我见过不少乙方朋友拿扫描器扫了一圈报告里全是中低危结果甲方不买账——为什么因为报告里没有把信息泄露和越权串成一条完整的攻击链路甲方看不到实际风险。所以我一直觉得这三类漏洞值得单独拿出来认真拆一遍。先说目录遍历本质上是程序在拼接文件路径时没有做合法性校验攻击者通过构造../这类特殊序列跳出原本限制的目录去读服务器上的任意文件。越权则是业务逻辑层面的缺陷——系统错误地信任了用户身份和他能访问的资源范围导致普通用户能看到或操作别人的数据。信息泄露更接地气就是敏感数据通过某种渠道暴露给了不该看到的人可能是报错页面、堆快照、备份文件、协议实现缺陷甚至是一行不起眼的注释。这三类漏洞为什么适合放一起讲因为它们在真实的攻击链路里经常是串联的一个目录遍历漏洞可能拿到配置文件配置文件里可能带着数据库密码或内网地址接着就能尝试越权访问管理接口最后造成大范围数据泄露。换句话说目录遍历和信息泄露往往是入口越权往往是扩大战果的那一步。这篇文章适合渗透测试新手、甲方安全工程师、开发人员在写代码时对照自查我也会结合最近的 CVE-2024-38819、Sa-Token 横纵越权、Spring Boot HeapDump 泄露这类实际案例来展开尽量讲清楚原理、复现思路和防御手段让你不只会扫漏洞还能真正理解漏洞背后的问题。2. 目录遍历漏洞从原理到最新CVE案例2.1 目录遍历的核心原理与危害边界目录遍历漏洞的原理说白了就是路径拼接不可控。很多业务场景需要根据用户输入来读取文件比如下载附件、导出报表、展示图片。如果代码直接写成file_get_contents(/var/www/files/ . $_GET[name])那攻击者提交一个name../../../etc/passwd拼接后的路径就变成了/var/www/files/../../../etc/passwd经过系统路径解析就到了/etc/passwd。这看起来是个很低级的错误但现实中出现的频率远超想象尤其是Java、Go、Python这类后端框架里如果你用了不安全的文件读取API又没做路径归一化很容易出事。危害边界需要说清楚目录遍历能读到的文件范围取决于Web进程的运行权限和操作系统对路径的解析规则。Linux下如果Web服务以www-data用户运行那/etc/shadow大概率读不到但/etc/passwd、应用配置、源代码、备份文件这些往往可以。Windows下因为盘符和反斜杠的存在利用方式更多比如构造..\..\..\Windows\win.ini这种路径。另外要注意目录遍历不只是读文件如果业务场景里有文件上传后按路径展示的逻辑可能还能配合写入或文件包含直接演变成RCE那级别就不一样了。这里要补充一个很多人容易踩的误区很多扫描器报目录遍历时给出的URL里只有../序列但应用的入口函数本身做了URL解码导致看似有漏洞实际上攻击者根本无法利用。所以我做测试时一般会手动验证几件事第一路径穿越后能否读到明确的敏感文件内容第二Web中间件如Tomcat、Nginx有没有对URL做归一化处理第三应用层有没有对文件名后缀做强校验。只有这三条都确认了我才会把这个漏洞写进报告的高危列表。2.2 实战复盘Spring Framework 目录遍历漏洞 CVE-2024-38819最近比较典型的是 Spring Framework 被爆出的目录遍历漏洞 CVE-2024-38819。这个漏洞影响Spring Framework 5.3.0到5.3.38、6.1.0到6.1.15等版本具体的问题出在静态资源处理上。当你配置了WebMvcConfigurer来处理静态资源映射并且使用PathResourceResolver时攻击者可以构造特殊URL绕过路径校验读取到Web应用根目录之外的敏感文件。我简单说一下我当时的验证流程。先搭了一个使用Spring Boot 6.1.14版本的应用配置了静态资源映射把/static/**指向本地目录。然后构造请求尝试在URL中加入编码后的路径穿越序列。这里有个关键点单纯提交../会被Spring的标准化流程拦截但如果把../进行URL编码比如用%2e%2e%2f在某些版本下就可能绕过检查。构造出来的请求类似GET /static/%2e%2e/%2e%2e/etc/passwd如果响应里看到了passwd文件内容就说明漏洞存在。修复方式也很直接升级到Spring Framework 5.3.39、6.1.16或更高版本即可。如果你因为某些原因不能马上升级临时缓解措施是重写PathResourceResolver对解析后的路径做一次强制校验确保最终路径仍在允许的根目录下。我个人建议在代码里加一层ResourceResolver的防御不要只依赖框架默认行为——因为这类漏洞已经出现不只一次了Spring过往版本里类似的目录穿越问题也有不少默认实现未必能防住所有攻击变种。2.3 目录遍历的自动化检测与手工验证方法自动化检测目录遍历很多工具比如Burp Suite的Active Scan、SQLMap的--file-read功能、nuclei的模板都能做。但工具给的结果一定要人工复核我见过太多误报。我的建议是结合流量日志先做一次黑盒探测把请求参数中所有可能是文件路径的字段提取出来比如filename、file、path、realPath、img分别尝试..、..%2f、%252e%252e%252f、....//、..%5cWindows等变形。手工验证时要特别注意编码层级的问题。有的应用会对输入先做一次URLDecoder.decode再做路径拼接有的则先拼接后解析。这两种情况对应的payload是不同层的编码。比如针对先解码一次再用的应用%252e%252e%252f会被解码成%2e%2e%2f如果应用没有再解码第二层File类解析时看到的还是%2e字符没法穿越。所以单纯拿公开的payload字典乱试效率不高你得先搞清楚目标应用的解码次数和中间层处理逻辑。我验证目录遍历时有一个习惯优先读取那些存在与否就能证明漏洞的文件。Linux下看/etc/passwdWindows下看C:\Windows\win.ini但这两个文件只适合证明能读不适合证明读取范围有多大。更好的做法是同时读应用自身的关键文件比如Java应用读application.properties、application.ymlPHP应用读config.php或.env这样能顺便判断后续攻击路径。如果读到了数据库连接串那就可以往数据库方向继续测试。2.4 目录遍历的修复与纵深防御方案修复目录遍历漏洞最稳妥的方案是白名单校验 真实路径校验双管齐下。白名单校验很好理解用户输入只能包含文件名不能包含路径分隔符和..序列不符合就直接拒绝。但实际业务里有些场景确实需要传入相对路径这时候必须在拼接后调用路径规范化函数比如Java的Paths.get(base, input).normalize()再用startsWith(base.toRealPath().toAbsolutePath())判断最终路径是否还在base目录内。注意要用toRealPath()因为它会处理符号链接避免攻击者通过软链接绕过。除了代码层修复中间件和运维层面也要做防护。Nginx层面可以加一条location规则拒绝URL中包含../的请求Tomcat层面配置allowLinkingfalse避免符号链接被解析。WAF规则如果能覆盖%2e%2e这类编码绕过也可以作为前置拦截。但我一直强调WAF和中间件配置只是缓解手段真正的修复必须是代码层的路径校验。因为攻击者总能找到新的编码方式绕过规则库你堵不住所有可能的变形。静态资源建议直接使用对象存储加CDN应用层不落盘从根上消除目录遍历的攻击面。3. 越权漏洞水平越权和垂直越权远比你想的复杂3.1 越权的本质与两种分类越权漏洞的根源是信任了不该信任的身份凭证。系统拿到用户的身份之后没有校验这个身份是否有权限访问目标资源就直接返回了数据。用生活里的例子类比门禁卡刷开了公司大门但你没权限进财务室结果财务室的门也没锁你推就开了——这就是典型的越权。越权分成水平越权和垂直越权。水平越权是同级别用户之间的越权比如登录用户A把订单ID从100改成101就查到了用户B的订单详情。垂直越权是低权限用户访问高权限功能普通用户调用管理员的删除接口直接执行了删除操作。从危害上看水平越权影响的是数据机密性和完整性大量用户数据可能被遍历垂直越权如果发生在后台管理功能上可能就是直接控制服务器了。实际测试中水平越权更常见因为很多开发人员只校验了是否登录没有校验资源归属。3.2 基于Sa-Token场景拆解横纵越权Sa-Token 是国内比较流行的Java轻量级权限认证框架它提供了登录认证、权限认证、会话管理等功能。相关热词里提到的Sa-Token 横纵越权其实是在说就算你用了权限框架也不代表一定安全。框架解决的是认证和授权的基础问题具体业务里的数据权限还是得靠开发者自己实现。我用一个常见的坑来解释。假设一个订单查询接口开发者在Controller上只加了SaCheckLogin这个注解只校验了用户是否登录并没有校验订单归属。用户A登录后调用GET /order/detail?orderId100拿到自己的订单然后把orderId改成101恰好是用户B的订单接口照样返回数据——这就是水平越权。Sa-Token的StpUtil.getLoginId()能拿到当前登录用户但系统不会自动帮你把用户ID和orderId绑定你得在Service层写一条判断查询出的订单.ownerId必须等于当前登录用户ID。再举垂直越权的例子。某个管理接口DELETE /admin/user/{id}如果只配置了SaCheckLogin没有配置SaCheckRole(admin)普通用户登录后直接调用这个接口就能删除用户。Sa-Token提供的SaCheckRole、SaCheckPermission注解就是用来做权限校验的前提是你在登录时把用户的角色/权限列表正确注入到了StpInterface实现里。我见过不少项目权限框架集成了一半注解倒是加了但StpInterface返回的是一个空的权限列表导致所有校验形同虚设。所以集成Sa-Token这类框架时一定要自测两件事第一全员权限列表是否准确第二接口上的权限注解是不是真的会拦截。3.3 越权漏洞的检测思路与手工验证技巧检测越权漏洞核心是身份切换和资源遍历。手工测试流程大概是这样的先准备两个测试账号A和B用A登录后抓取所有请求把请求中涉及ID类参数订单号、用户ID、文章ID、文件ID全部记录下来然后用B登录尝试访问A的资源对应的请求把A资源ID替换到B的请求里看响应是否返回了A的数据。这里有个很容易忽略的细节替换ID之后要注意响应里有没有泄露另一个用户的信息。有些系统很鸡贼接口返回的JSON里没有直接显示敏感字段但页面上渲染出了用户名、手机号或者收货地址一样算越权。另外越权不只是GET请求POST、PUT、DELETE请求都要测试。特别是修改类接口如果只能改自己的信息但接口没校验资源归属你完全可以把B的ID放进去把B的密码改掉这就是水平越权的写操作危害更大。垂直越权的检测相对简单但需要你提前了解目标系统的角色权限矩阵。通过注册一个普通用户或者干脆用未登录状态去访问后台管理接口列表看哪些接口没有被权限拦截。这里我常用一个技巧先看前端路由有没有隐藏的管理端入口然后从JS文件里提取后端接口路径构造一个未授权访问接口字典批量测试。很多系统的管理员接口只做了前端菜单权限控制后端接口裸奔这种问题在新开发的系统里特别常见。3.4 从权限设计层面根治越权要从设计层面解决越权首先要建立对象级权限校验的意识。所谓对象级权限就是每次访问一个具体资源时都要明确当前用户对这个资源是什么关系。是所有者是同一部门还是公开资源只做一个全局的SaCheckLogin是不够的必须在查询或操作资源的Service方法里把资源归属者与当前用户关联起来。其次建议在开发阶段就引入统一的权限校验工具类。比如封装一个ResourceOwnershipValidator.verify(resource, currentUser)方法在Controller层掉接口之前统一调用避免每个业务都重新写一遍校验逻辑。这样做的最大好处是代码审查的时候能一眼看出哪些接口漏了校验。我见过很多项目漏洞产生的原因就是同一个接口在功能分支上写了一遍校验在主分支上忘了写上线后主分支的代码生效漏洞就出来了。还有一个容易被忽略的点批量查询接口。很多系统提供的列表查询接口会把人名、手机号、订单金额返回到列表里如果查询条件里不带用户ID就可能返回所有用户的数据。这种接口甚至不需要改ID直接访问就是水平越权信息泄露的组合。测试时不要只盯着详情接口列表接口要仔细看请求参数和响应体里的数据范围。4. 信息泄露最容易被忽视也最容易出大事4.1 信息泄露的常见场景与攻击链路价值信息泄露这个名词听起来比目录遍历和越权温和但实际危害取决于泄露了什么。泄露一条/etc/passwd如果没有可利用的账号hash威胁也许有限但泄露一份包含了OSS AccessKey、数据库密码、Redis密码的application.yml那基本等于把整个内网拱手送人。所以我做安全评估时非常看重信息泄露点在整个攻击链里的提权作用。从攻击者视角看信息泄露往往是第一步侦察的成果。常见泄露场景包括Nginx配置错误导致备份文件可访问backup.zip、www.zip、Spring Boot Actuator未授权访问/actuator/heapdump、Swagger/API文档未限制访问、报错页面打印SQL语句和堆栈、调试模式下控制台暴露完整请求日志、/.git目录可遍历导致源码泄露、对象存储桶权限配置错误等等。每一条泄露点都可能组合出后续攻击路径所以绝对不能用信息泄露只是低危的心态来对待。4.2 Spring Boot HeapDump泄露一次典型的敏感信息挖掘Spring Boot项目如果引入了Actuator依赖且没有正确配置权限/actuator/heapdump端点可以直接下载Java堆转储文件。堆转储文件是JVM内存的镜像里面包含所有运行时对象包括配置类、数据库连接池对象、线程局部变量。如果项目把数据库密码、第三方密钥、Admin后台登录token放在内存或配置对象里攻击者下载heapdump后用MATMemory Analyzer Tool或Eclipse MAT打开搜索关键词password、secret、token、accessKey往往能直接翻出明文密码。我印象很深的一次测试目标是一个内网管理系统。我先访问/actuator发现暴露了heapdump端点于是下载了约800MB的heapdump文件。用MAT加载后在OQL里搜索包含password字段的对象很快就找到了一个JdbcDataSource对象明文数据库密码就在里面。更离谱的是我在一个Map类型的对象里搜到了一个adminToken这个token是后端调用管理系统自己接口用的凭证拿它直接登录了后台管理界面整个过程不超过十分钟。修复HeapDump泄露其实不难生产环境关闭Actuator的敏感端点或者通过Spring Security限制/actuator/**只能内网IP访问。但很多团队在开发时打开了全部端点部署到生产时忘了改配置就会埋下雷。我建议在所有Spring Boot项目的application.yml里明确配置management.endpoints.web.exposure.includehealth,info这样的白名单而不是用*同时给/actuator/**加上IP白名单。另外还要注意一个小坑即使你只暴露了health端点如果底层依赖没有升级也可能存在其他利用途径所以依赖版本管理也很重要。4.3 SSL/TLS协议信息泄露漏洞CVE-2016-2183原理扫描的来龙去脉很多扫描报告里会出现CVE-2016-2183 SSL/TLS协议信息泄露漏洞【原理扫描】这个漏洞全称是基于分组密码的SSLVPN与TLS协议信息泄露漏洞。原理扫描是相对于验证扫描而言——扫描器并没有真正利用漏洞而是通过识别目标的加密套件Cipher Suite配置判断其使用了弱密码套件比如3DES CBC模式于是给出原理上存在风险的结论。3DES已经是很老的对称加密算法了它的有效密钥强度只有112比特左右加上CBC模式如果IV和填充处理不当可能被BEAST这类攻击利用所以业界早已建议禁用。扫描器检查的原理是TLS握手时客户端和服务端协商加密套件如果服务端响应中包含TLS_RSA_WITH_3DES_EDE_CBC_SHA这类弱套件就报CVE-2016-2183。这类漏洞本身不一定能被直接利用但它是合规审计和等保测评里的常见扣分项。修复思路是修改服务端的TLS配置禁用3DES和CBC类弱套件启用AEAD类套件如TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256。Nginx里通过ssl_ciphers指令配置Java应用则要修改JVM的java.security文件或者启动参数。做这块的时候要注意兼容性问题如果禁用了太多个老套件老版本的浏览器或客户端可能连不上。我的做法是保留TLS 1.2和TLS 1.3只禁用3DES、RC4、DES这类明显弱到不行的套件对业务影响最小。4.4 信息泄露的排查方法与收敛建议排查信息泄露我通常从四个层面入手。第一是Web层检查/actuator、/.git、/swagger-ui.html、/api-docs、/WEB-INF/web.xml、备份文件等常见路径是否存在未授权访问这一步可以用目录扫描工具但要记得加-x参数去排除200误报。第二是报错信息层故意触发一个异常看HTTP响应体里是否包含堆栈、SQL语句、敏感配置项。第三是响应头层确认服务器不会在响应头里带出内网IP、版本号、调试开关等信息。第四是网络协议层检查TLS/SSL配置、端口暴露范围。收敛建议其实很朴素敏感端点一律加认证错误页面统一返回友好提示不打印堆栈响应头隐藏服务器版本备份文件不要放在Web目录下代码仓库不要把密钥提交进去用配置中心管理。这些听着都是基础操作但我在实际项目里遇到的绝大多数信息泄露都是基础操作没做好。所以这里想提醒做开发的朋友上线前可以拿扫描器扫一遍自己部署的应用别等安全团队来开奖。5. 三类漏洞的关联分析与综合防护5.1 攻击链视角目录遍历→信息泄露→越权把三类漏洞放在一条攻击链里看思路会清晰很多。一个典型的攻击路径是这样的扫描发现目录遍历漏洞读取application.yml获得数据库连接信息然后连接数据库找到管理员用户的哈希如果能进一步通过信息泄露拿到某个内部系统的token就直接用token调用管理接口完成越权。每一步单独看可能都是低危但连起来就是一次完整的严重入侵。这也是为什么我在工作报告里特别强调漏洞组合利用的重要性。只报一个目录遍历运维同事可能觉得反正读不到什么敏感文件只报一个越权开发可能觉得数据量不大影响有限。但你把攻击链画出来让他们看到一份几百GB的客户数据可能被拖走重视程度完全不一样。安全评估的价值不只是罗列问题而是把风险按业务影响排序帮团队决定先修什么。5.2 一套可落地的安全基线结合这三类漏洞我整理了一套适合中小团队落地的安全基线可以直接抄作业。第一代码层面强制要求所有涉及文件操作的接口必须做路径规范化校验所有涉及数据查询的接口必须做对象级权限校验密钥、密码、token严禁硬编码在代码或配置文件中要放到环境变量或配置中心。第二框架和中间件层面Spring Boot项目建议使用最新稳定版如Spring Boot 3.2.x以上Actuator端点只暴露health和infoNginx和Tomcat禁用目录列出TLS协议使用1.2以上版本禁用3DES和RC4套件。第三上线前自测流程每个接口至少执行一次越权检查用测试账号A访问测试账号B的资源目录遍历检查要覆盖%2e%2e%2f、%252e等编码变形信息泄露检查要覆盖Actuator、Swagger、堆转储、备份文件、错误页。第四定期巡检每季度用扫描器或安全审计工具跑一遍内网应用对照基线核查。这里我特别建议自动化越权扫描虽然现在很多工具做得还不够好但至少可以把检测一类资源ID是否越权这个动作脚本化纳入CI流程。5.3 安全测试中的注意事项与合规边界最后想聊一个很少在技术文章里被讲透、但每个安全从业者都必须清楚的问题做这些测试的边界。目录遍历、越权、信息泄露的测试对象必须是你有授权的系统无论是自己公司的、甲方委托的还是CTF里专门搭建的靶标。没有授权去测试别人系统不管初心是什么在法律上都是越界行为这点没有任何商量余地。在授权测试内部也要注意控制影响范围。验证目录遍历时读一个/etc/passwd证明漏洞存在就够了不要继续往下尝试读数据库配置和后端源码更不要尝试连接内网数据库。验证越权时用测试账号确认能读取另一个测试账号的数据即可不要用真实客户数据验证。信息泄露也一样发现heapdump后确认存在泄露即可不建议把整个堆文件下载到本地慢慢翻——除非甲方授权让你做全量数据分析并出具报告。我个人的习惯是测试过程中产生的敏感数据文件一律加密存储交付报告后删除不给客户留隐患。6. 常见问题排查速查表现象可能原因排查思路修复建议扫描器报目录遍历但手工无法利用URL编码层级不匹配或中间件拦截了../确认应用解码次数、中间件归一化行为以手工复现为准防止误报同时检查代码层是否已做路径校验越权测试时替换ID无响应接口可能校验了User-Agent、签名、Token或资源归属对比测试账号A与B的请求头差异检查是否存在额外的鉴权参数确认是否有其他鉴权机制若确认越权则修复资源归属校验/actuator/heapdump下载无权限未暴露该端点或Spring Security拦截了路径访问 /actuator 查看端点列表尝试绕过路径如/actuator/heapdump;.js按4.2的建议收缩端点暴露范围TLS扫描提示CVE-2016-2183服务端启用了3DES等弱加密套件用openssl查看s_client协商结果修改Nginx/JAVA配置禁用弱套件备份压缩包直接可访问备份文件被放在了Web根目录下检查backup.zip、.tar.gz等路径修改备份位置Web目录不放置任何备份文件报错页面出现SQL堆栈全局异常处理器未配置触发一个参数错误查看HTTP响应统一返回友好错误页面堆栈记录到日志文件信息泄露中发现了明文密码配置中心未启用密码写在配置文件内把泄露密码的配置文件和业务实现放到一起排查使用Vault等配置管理工具或环境变量注入这张表里每条你都可能在日常测试中碰到。我特别想强调的是第一行和第三行扫描器报出来的漏洞一定要手工复核因为误报会浪费开发人员大量时间而真正需要优先修复的是那些能证明存在、且能被实际利用的漏洞。别让报告躺在那里也别被报告里所有条目吓到——把风险排序做好一个个闭环修复安全工作就是这样一点点做扎实的。我做了这些年的安全测试最大的体会是这三个漏洞类型听起来基础但它们的组合在真实攻击里价值极高。能解决为什么——为什么文件读取会变成任意文件读取、为什么登录了却还能访问别人数据、为什么一个堆转储文件里全是宝贝——比单纯会跑扫描器重要得多。希望这篇文章能帮你把这些点串起来毕竟安全攻防说到底拼的还是对每个细节的理解。