ARTICLE DETAIL

资讯详情

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

Web安全高频漏洞实战:目录遍历、越权与信息泄露

Web安全高频漏洞实战:目录遍历、越权与信息泄露 目录遍历、越权、信息泄露这三类漏洞在我做安全测试的这几年里几乎是出场率最高的“老三样”。很多系统表面上看风平浪静登录有验证码、接口有签名、后台有权限控制但一旦把注意力放到那些不起眼的边缘功能上——一个文件下载接口、一个订单查询参数、一个调试开关问题就像竹筒倒豆子一样全出来了。某个客户系统就是这么翻车的下载附件的地方能用../跳到服务器任意目录订单查询的接口改一下ID就能看到别人的订单一个没关掉的Actuator端点直接把JVM内存里的数据库密码和Token全部暴露了出来。这篇东西我就把这三大类问题的原理、利用姿势、真实案例和修复方案摊开来讲内容偏实战适合刚接触Web安全的测试人员也适合写代码的时候想少踩几个坑的开发朋友。1. 三类漏洞的共同底色都在突破“信任边界”很多人第一次接触这三个漏洞会觉得它们风马牛不相及一个和文件路径有关一个和权限逻辑有关一个和数据暴露有关。但如果你把它们放在“信任边界”的框架下去看会发现它们的底层逻辑出奇地一致。1.1 信任边界从用户输入到资源访问先问一个问题一个Web应用到底在信任什么它在信任用户的输入——参数里给什么文件名就去拼接路径找文件它在信任会话的身份——只要登录过就认为你有权限访问某些数据它也在信任自己的运行环境——认为内存中的数据不会被外部窥探认为网络传输是安全的。这三份信任恰恰是攻击者最想打破的东西。目录遍历打破的是“输入信任”攻击者往文件路径参数里塞入../就能逃出web目录的围栏去读取服务器上的任意文件越权打破的是“身份信任”攻击者明明只是个普通用户却因为接口只校验了“是否登录”而没校验“能否操作这份数据”把别人的订单、文档、配置看个精光信息泄露打破的则是“环境信任”应用开发者默认调试接口不会被人发现默认内网数据不会传到公网默认协议加密就万事大吉结果一个HeapDump文件把密钥送给攻击者一条3DES弱加密套件让通讯内容在理论上有被破解的风险。用一个生活化的例子来理解这就好比一栋写字楼目录遍历相当于你拿着任意楼层的门禁卡刷开了机房的门——本来只该让你进入一层的接待区但门禁系统压根没检查你会刷到哪一层越权相当于你虽然是普通员工却跑到别的工位拉开了抽屉翻别人的文件信息泄露则相当于公司的玻璃幕墙没贴隐私膜外面路过的人能把会议室屏幕上的PPT看得一清二楚。1.2 为什么这三类漏洞常常被放在一起讨论把这三类漏洞放到一起不仅仅是“它们都是Web安全经典问题”。实际做渗透测试的时候你很容易发现它们是彼此串联的目录遍历读到了数据库配置文件里面躺着数据库账号和Redis密码顺着这些凭据连进了内网系统发现前端页面里到处是用户ID改一下ID就直接水平越权拿到了管理员的个人数据再翻一翻系统日志发现日志里居然打印了完整的请求参数包括Token和验证码。这一套组合拳打下来一条完整的高危漏洞链就成型了。从防御方的角度看这三类漏洞也有一个共同特点——它们都不是“防不住”的漏洞更准确地说是“想当然”导致的漏洞。开发者觉得路径会过滤、权限会校验、敏感接口不会被发现这种想当然比技术栈本身的老旧更加致命。理解了这一层再看后面每一类漏洞的具体细节就会有一种“看山不是山”的感觉你不再只是记住../怎么打、ID怎么改、端点怎么找而是能站在更高的视角去预判一个系统哪里最容易突破。2. 目录遍历从历史经典打法到CVE-2024-38819的演变目录遍历有另一个流传更广的名字叫“路径穿越”英文叫Path Traversal。它的危害我想不用多强调——轻则读取/etc/passwd或者web应用的源码重则配合文件写入功能直接拿服务器权限。它的起源其实非常古老Apache、IIS、Tomcat这些老牌中间件在二十年前就出过一堆路径穿越漏洞但直到今天它依然活跃在各种自研系统里而且随着框架越来越复杂出现了新的变种。2.1 目录遍历的经典成因路径拼接与过滤缺失经典目录遍历的成因简化到极致就一句话把用户输入直接拼到文件路径里却没有校验最终路径是否还在允许的目录内。最常见的代码长这个样子Java伪代码String fileName request.getParameter(fileName); String basePath /data/files/; File file new File(basePath fileName); // 直接读取文件并返回内容如果用户传进来的fileName是../../../../etc/passwd拼出来的完整路径就变成了/data/files/../../../../etc/passwd。操作系统解析路径的时候..会逐级向上跳转最终读到的就是/etc/passwd。这类漏洞在真实的系统里通常出现在这些位置文件下载接口?fileName、?path、?url这类参数最容易出问题文件预览接口在线预览图片、PDF、Office文档时如果通过文件名直接定位文件导出/导入功能导出模板、导入回显、批量打包下载等场景主题/模板切换有些系统允许通过参数切换前端模板、语言包参数值可能就是目录名压缩包解压功能压缩包里的文件名如果带../解压时会逃逸到指定目录之外Zip Slip经典的手法也相对固定。Linux下用../../逐级上跳Windows下既有../../也有..\和盘符跳转比如..\..\boot.ini。过滤不严的时候还可以结合URL编码绕过把.编码成%2e把/编码成%2f把../整体编码成%2e%2e%2f甚至二次编码%252e%252e%252f。这些绕过技巧本质上是在利用服务器对URL解码次数和层级的理解差异——你解码一次前端可能过滤前解码后的结果但如果过滤器和解码器各处理一层就会出现绕过的缝隙。2.2 CVE-2024-38819Spring Framework静态资源解析的新盲区如果说老的目录遍历是“裸奔”级的漏洞——代码里压根没过滤——那么近几年的目录遍历漏洞则更隐蔽它们往往藏在一众知名框架的核心逻辑里。2024年下半年披露的CVE-2024-38819就是一个典型的例子。这个漏洞出在Spring Framework的静态资源处理模块。简单说当应用通过WebMvc或者WebFlux配置了静态资源映射时比如把/static/**映射到classpath:/static/目录攻击者可以通过构造特殊格式的请求URL绕过Spring的资源路径校验规则读取到映射目录之外的文件。如果你了解Spring处理静态资源的内部机制就知道它有一个PathResourceResolver负责把请求URL“翻译”成真实的资源文件。这个解析器本身做了路径规范化处理会拦截包含..的穿越请求。但问题在于Servlet容器比如Tomcat对URL路径的解析方式和Spring存在差异——当URL中包含分号、参数、特殊编码时容器和框架各自会先把路径处理一遍处理结果可能截然不同。攻击者利用这种“解析差异”可以让容器认为请求的是一个合法静态资源而让Spring在解析时实际跳出了允许访问的目录这就绕过了防护。具体来说受影响的版本大致包括Spring Framework 5.3.x系列、6.0.x系列和6.1.0到6.1.12之间的版本官方在5.3.40、6.0.24、6.1.13等修复版本中对资源解析逻辑做了加固。从本质上看这个漏洞和CVE-2024-38816HTTP请求走私的根因有相似之处都与容器和框架之间对URI各部分的解析差异有关。这类“框架级目录遍历”的可怕之处在于业务代码一行没改防御做得再好框架底层一出现绕过点所有依赖该框架的应用全部中招。这也解释了为什么你在做安全监控时看到扫描器报出这个CVE标识的时候第一反应不应该是质疑“这个系统没做路径过滤吗”而是立刻去核对Spring的版本号是否在受影响区间内。2.3 修复目录遍历的防御要点与绕过套路清单针对目录遍历防御方的思路经历了从“黑名单过滤”到“白名单校验”再到“框架级修复”的演进。这里我整理一份实战中验证过有效的防御要点和绕过思路对照防御手段为什么有效攻击者思考的对应绕过方式过滤../、..\等关键字符最基础的黑名单挡住脚本小子URL编码、双编码、Unicode编码绕过使用Path.normalize()规范化后再校验前缀从路径语义上消除..寻找校验与读取之间的路径理解差异如符号链接白名单校验文件后缀/文件名规则从根本上限制输入范围寻找白名单内的敏感文件如.properties、.log把真实文件名保存在数据库用ID下载用户根本不接触路径遍历ID批量下载所有文件等于没做访问控制升级框架版本修复框架层解析盲区寻找其他框架或容器的同类解析问题我自己在做代码审计的时候判断一个路径操作是否安全最有效的办法不是去看过滤逻辑写得多么严密而是顺着参数追问一句话最后这个文件的绝对路径到底有没有被严格限制在一个预设目录里只要限制住了过滤不过滤反而是次要问题。反过来如果只是简单地replace(../, )而不做最终路径校验那我几乎可以断定找一个双写绕过或编码绕过的 payload 就能打穿。实操中还有一个非常容易被忽略的目录遍历出口——压缩包解压。很多系统有导入功能接受用户上传的zip并自动解压。如果解压时没校验压缩包内每个条目的文件名攻击者可以构造一个包含../../shell.jsp的压缩包解压后文件直接落到了web目录下的可执行目录。这就是业内常说的Zip Slip漏洞危害不亚于任意文件写入实际遇到的概率比普通的路径穿越参数还要高。3. 越权漏洞水平越权与垂直越权以及Sa-Token场景下的思考越权漏洞用安全圈的行话说叫IDORInsecure Direct Object References不安全的直接对象引用但在中文语境下大家更习惯叫它“越权”。它属于逻辑漏洞里最高发的一类几乎不需要花里胡哨的利用姿势只要会改参数就能测出来。我见过太多系统安全测试报告里其他的问题都能整改唯独越权修复起来最让开发团队头疼因为它不是打补丁能解决的而是整个权限模型的架构性问题。3.1 越权的本质认证与授权的边界混淆把越权拆开通常分两种水平越权和垂直越权。水平越权指的是一个普通用户通过修改请求参数访问到了另一个同级别用户的私有资源。最典型的就是订单查询接口长这样/api/order/detail?id12345登录状态校验也做了但ID是连续的数字把id改成12346看到的就是别人的订单信息。这类问题通常出在“只校验了登录状态没校验数据归属”的开发思维上。垂直越权则是纵向的低权限用户比如普通员工通过构造请求执行了高权限操作比如管理员才能调用的接口。这个在Web应用里也很常见按钮在前端隐藏不代表后端接口不存在普通用户直接构造一个POST请求打向/api/admin/deleteUser如果后端没有做角色校验同样能执行成功。为什么这两类问题在真实业务系统中如此普遍归根结底是因为很多开发团队把“认证”和“授权”混为一谈了。认证解决的是“你是谁”登录之后给你发一个Token之后的每个请求带着Token就默认通过了但授权解决的是“你能干什么”这一步需要在每个涉及资源访问的接口里去校验当前用户对目标资源是否有操作权限。很多时候开发只做了前者后者完全依赖前端隐藏按钮来“实现”——这在安全视角下等于没有防护。对比维度水平越权垂直越权攻击者身份普通用户低权限用户越权方向横向访问同级他人数据纵向执行高权限操作常见场景订单、用户信息、文件、消息管理后台、审核接口、系统配置接口根因缺数据级权限校验缺功能级角色校验典型修复校验数据归属或引入数据权限接口级增加角色/权限鉴权3.2 Sa-Token横纵越权的典型场景复现之所以要单独提Sa-Token是因为它是目前Java生态里非常流行的轻量级权限认证框架大量新项目都在使用。很多开发选型的时候有个错觉“用了Sa-Token权限安全就没问题了。”实际上Sa-Token解决的是会话管理和角色权限控制它本身不背越权的锅越权漏洞依然大面积出现在用了Sa-Token的系统中。我在评估一个基于Sa-Token的业务系统时碰到过这样一个场景系统里有一个用户信息查询接口代码大致是GetMapping(/user/info) public Result getUserInfo(RequestParam Integer userId) { // 从Session中获取当前登录用户 StpUtil.checkLogin(); // 直接使用前端传入的userId查询 User user userService.getById(userId); return Result.ok(user); }攻击者登录自己的账号后把userId改成别人的ID就查到了别人的手机号、身份证号、家庭住址。这就是教科书级别的水平越权。而另一个管理端接口PostMapping(/admin/resetPassword) public Result resetPassword(RequestBody ResetDTO dto) { // 只校验登录没校验角色 StpUtil.checkLogin(); adminService.resetPassword(dto.getUserId()); return Result.ok(); }普通用户登录后直接POST这个接口就能重置任意用户的密码。这就是垂直越权。从测试的角度看这两个漏洞发现起来毫无难度但它们的出现恰恰说明了一个问题开发用了Sa-Token的checkLogin()checkRole()这类API但并没有在每一个涉及敏感操作的接口上把该做的权限校验做全。框架给了你武器但你没有在全部防御点上使用它。另一个Sa-Token场景里容易出现的“横纵”交织情况是开发在一个接口里结合了用户身份和数据操作但没有区分“当前登录用户”和“操作目标用户”。比如一个修改资料的接口预期是用户只能改自己的资料但代码从参数里取了userId而不是从会话里取就造成了水平越权。如果再配合请求另一个管理接口就又升级成了垂直越权。这就是为什么热词里会把“横纵越权”并列——它们在同一个系统里往往是结伴出现的检测到了一个另一个大概率也存在。3.3 越权检测思路与数据级权限的修复方案越权漏洞的检测说到底就是两件事遍历ID和换角色重放。遍历ID很好理解——找到一个带数值参数的接口按顺序或按规律修改参数值观察响应内容是否包含了不属于当前用户的数据。这里我分享一个提高效率的技巧不要只盯着数字ID很多系统用UUID、雪花ID这样的非连续标识你以为没法遍历但接口可能同时支持用手机号、邮箱、用户名甚至订单号查询。另外修改参数的时候要注意观察响应的“间接变化”有时候接口本身不直接回显数据但响应时间、报错信息、重定向目标会有差异这些差异同样可以作为判断依据。换角色重放则是垂直越权的标准测法准备普通用户A和管理员用户B两个账号先用B登录抓取高权限接口的请求包退掉再换A登录把请求包原样重放。如果A也能成功执行那就是垂直越权。这个过程听起来简单但实际测试中有一个很容易踩的坑——高权限请求包里往往带有管理员专属的Token、Cookie或者自定义Header字段比如X-User-Role: admin换账号重放时如果不把这些身份标识一并替换掉判断结果就会被干扰。修复方案的层面我始终坚持一个观点越权问题要用数据权限模型去解决而不是靠过滤器去堵。具体有三个层级第一层接口级鉴权用Sa-Token自带的SaCheckRoleSaCheckPermission注解或拦截器把接口对应的角色、权限点写清楚这一步解决垂直越权。第二层数据级校验在涉及查询和操作的Service层里把“当前登录用户ID”作为必要条件拼进查询条件或更新条件。比如查询订单应该用WHERE id ? AND user_id ?而不是WHERE id ?。这一步解决水平越权。第三层统一的数据权限组件如果在复杂的业务系统里每个Service手写数据归属校验很容易遗漏那就需要抽出统一的数据权限框架——比如把数据操作都收敛到DataScope这样的业务查询范围类中由统一方法附加当前用户的可访问范围条件。在代码审计中我见过最不负责任的修复方式是在接口里判断“如果ID等于当前用户ID才放行”。这种修法等于告诉攻击者你只需要找到一个别人账号的ID再想个办法绕过前端校验就能照样越权。4. 信息泄露从HeapDump到传输层泄露的完整视图信息泄露是整个安全领域里最宽泛的一个话题从HTTP响应头里带出来的服务器版本号到数据库里几千万条用户数据被脱裤都算信息泄露。在这篇文章里我重点讲两个在2024-2025年热度非常高、而且和前面两类漏洞经常联动的具体场景Spring Boot HeapDump泄露以及SSL/TLS弱加密套件导致的协议层信息泄露。4.1 Spring Boot HeapDump泄露从端点到密钥Spring Boot是目前Java后端的事实标准而Spring Boot Actuator提供了一组用于监控和管理的生产级端点。问题在于很多团队上线的时候忘记做安全配置导致这些端点赤裸裸地暴露在公网。其中最有“含金量”的端点之一就是/actuator/heapdump——它能导出当前JVM进程的堆内存快照。你可能会问一个堆内存快照能泄露什么我在分析一次授权测试的heapdump时用Eclipse MAT打开一个大概1.2GB的堆转储文件然后做了几步简单操作先看字符串信息。HeapDump里存了所有对象的字符串值直接用MAT的OQL查询搜索包含password、secret、token、key的字符串几乎一搜一个准。最常见的泄露内容包括数据库连接串里面的DataSource配置对象会保存JDBC URL、用户名和明文密码Redis等中间件密码Jedis/Lettuce连接池里同样能挖到OAuth Token / JWT密钥内存里往往缓存了调用第三方接口用的access_token、refresh_token以及JWT的签名私钥用户敏感信息搜索phone、email、idCard经常能捞出大量真实用户数据SSH/HTTPS私钥读取配置时加载进来的私钥对象也留在堆里实操中会发现heapdump文件动辄几百MB甚至几个GB直接全量分析非常消耗时间和内存。我的经验是先别急着打开MAT而是用命令行工具快速过滤# 先用strings提取可打印字符串再用grep过滤关键词 strings heapdump.hprof | grep -E (jdbc:|password|secretKey|token) | head -100这一步能快速定位疑似敏感信息的位置和上下文然后再针对性地用MAT做对象追踪效率会高很多。还有一种思路是把HeapDump文件丢给专门的分析脚本很多SRC平台上都有现成的heapdump敏感信息扫描工具原理其实就是对字符串做规则匹配比手工看快得多。这类泄露的修复方案很直接生产环境禁止暴露/actuator/heapdump、/actuator/env、/actuator/mappings等敏感端点或者给Actuator端点加Spring Security认证。再往前走一步还可以在网络安全组层面限制/actuator/*路径只允许内网/堡垒机IP访问形成双重保险。这里想强调一个理念敏感端点的暴露面控制不只是开关一个配置项而是要在网络层、应用层、运维层各设一道闸。4.2 SSL/TLS协议信息泄露CVE-2016-2183原理扫描与验证第二个信息泄露场景来自传输层。CVE-2016-2183对应的就是SWEET32攻击——一个针对64位分组密码主要是3DES的生日攻击。这里的关键点在于“3DES”这类算法使用的是64位固定分组长度的加密而现代推荐的AES使用128位分组。在分组加密的CBC模式下当同一密钥加密的数据量达到一定规模时由于生日悖论两个密文分组大概率会发生碰撞攻击者通过对比碰撞块的异或值可以逐步推算出明文的敏感信息。理论上有趣实际攻击门槛也很高因为它要求攻击者能观察大量同密钥密文——差不多要32GB的数据量而且在现代网络环境下获取如此大规模的密文需要长时间被动监听。但为什么这个漏洞在扫描报告中如此常见因为它通常是“原理扫描”——扫描器比如Nessus、OpenVAS或者各类云安全中心的基线检查只要发现服务端支持3DES系列的密码套件比如TLS_RSA_WITH_3DES_EDE_CBC_SHA就直接报漏洞。它不需要真的监听32GB流量来验证而是“你配置了弱算法我就认为你有风险”。这是一种偏稳妥的风险评估思路你不一定马上就会被攻击但你的“安全水位”不合格。验证一个服务端是否支持弱加密套件可以用OpenSSL手动探测# 查看服务端支持的TLS密码套件 openssl s_client -connect target.com:443 -cipher 3DES /dev/null如果服务端能握手成功说明它确实支持3DES套件。还可以用nmap --script ssl-enum-ciphers -p 443 target.com做一次全面的套件枚举输出的结果里会明确列出每类算法的评分。修复手段就是在Nginx、Apache、负载均衡或者云SLB上调整TLS配置文件把3DES从密码套件列表里剔除。比如Nginx是这么配置的ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;配置完记得用上面的openssl s_client命令反向再测一遍确认3DES已经彻底关闭。这类问题看起来简单实际在老旧业务系统里经常被忽略因为老客户端比如Windows Server 2008上的IE、老版微信内置浏览器可能并不支持新的加密套件运维为了兼容性保留了3DES。这里我给的实操建议是可以先通过监控确认线上客户端对TLS版本和套件的实际使用分布如果3DES的使用量已经趋近于零放心关闭如果还有零星的兼容性需求至少要在WAF或网关层针对性地做限制而不是让弱套件长期暴露。4.3 信息泄露的“量化”评估从海量数据里筛选真正的高危对象在没有出漏洞之前很多团队对“信息泄露”的理解停留在“哪里有敏感词”的层面等真正的泄露发生时才慌了神。这就是为什么我强烈建议——安全团队在做日常风险评估的时候应该用“量化”的思维去看一个系统里有哪些值得保护的信息以及如果泄露对业务的影响是几级。这个“量化”思路在实战中的操作方式大概是把信息资产按敏感程度分档。第一档被称为“直接危害类”比如数据库密码、云厂商AK/SK、JWT签名私钥、SSH私钥这类信息一旦泄露攻击者可以直接接管系统第二档是“间接危害类”比如用户手机号、身份证号、真实姓名、地址这类信息能辅助社工或者撞库第三档是“基础泄露类”比如服务器Banner信息、绝对路径、框架版本号这类信息单独看危害不大但能给攻击者做后续攻击提供线索。有了这个量化的分级之后再去看一条信息泄露线索优先处理顺序就非常清晰了——先解决第一档再逐步收敛第二档第三档作为常态化治理的范畴。这个思路放在前面的目录遍历和越权场景里同样适用目录遍历读到了什么文件决定了漏洞的真实严重性读到静态页面是一回事读到配置文件是另一个量级的风险越权接口能访问什么数据决定了影响范围只能看别人昵称是低危能看到身份证和银行卡那就是高危中的高危。给“泄露”“越权”“遍历”都加上定级维度之后你写出的渗透测试报告就不再是漏洞名词的罗列而是一份业务风险管理报告。5. 一条真实漏洞链三个问题的组合利用与排查复盘单独看每个漏洞可能都让人觉得“不过是几行代码的问题”但在真实的攻防对抗中这三个漏洞经常被攻击者串成一条完整的链条。我在一次授权范围内的漏洞挖掘中遇到过一个系统印象非常深刻这里把它拆开复盘你会更清楚攻击者是怎么利用“小问题”撬动“大权限”的。5.1 组合利用的典型链条从路径穿越到管理员数据那是一个政府类的信息管理系统前端是Vue后端是标准的Spring Boot MyBatis Plus。常规的参数注入、未授权访问测了一圈都没发现明显的入口。随后我把注意力放到了一个不起眼的“附件预览”功能上请求长这样GET /file/preview?fileName2024/report_001.pdf习惯性地把fileName参数改成../../../../etc/passwd返回内容前几行直接是root:x:0:0:root:/root:/bin/bash。目录遍历漏洞确认而且文件内容回显在响应体里。拿到目录遍历之后我没有停在这里而是开始思考一个问题这个接口能读哪些文件系统的部署路径能通过报错信息推断出来于是顺着路径往下读先是读了application.yml里面配置了数据库地址、账号、密码以及Redis的密码。我像开盲盒一样又读了一份application-prod.yml里面的数据库密码是明文而且能通过公网IP直连。到这里攻击者本来已经可以直接连数据库了。但更戏剧性的事情在后面我在代码包里翻到了一个定时任务类里面读取的是用户表的统计信息而用户姓名、身份证号、手机号在开发阶段为了测试方便全部以明文存了进去。这意味着数据库一旦被攻入级联泄露的就是所有实名用户信息。这一个链条走下来起点仅仅是一个“低危”的目录遍历参数终点却是数据库拖库级别的信息泄露。如果当时我停在了“验证了目录遍历就收工”这个问题可能最终只被当作一个“中危”缺陷来修复——说不定还因为找不到具体业务影响被驳回。但实际上它的真实危害已经达到了“严重”级别。这就是为什么我一直强调做渗透测试一定要有“链式思维”漏洞的价值在于它能让你够到多远的地方而不是漏洞本身的名字有多吓人。5.2 排查链路复盘越权接口如何加快漏洞定级再往前推一步分析一下这套系统里为什么越权和高危泄露会如影随形。在利用目录遍历读取到应用源码后我把注意力放在了用户管理模块。通过分析Controller代码我找到了一个管理端接口可以查询所有用户的基本资料。按照垂直越权的测试思路我用一个普通测试账号登录系统直接构造请求访问这个接口管理端并没有做角色校验响应包里把所有用户信息全部吐了出来。这个接口的鉴权逻辑和前端路由里的“管理员菜单”完全绑定——前端把入口隐藏了后端却连最基本的RequiresRoles(admin)都没加。这一个越权接口的问题让整个漏洞链的定级从“敏感信息泄露”直接升级为“大规模用户数据泄露风险”目录遍历让攻击者拿到了数据库口令垂直越权让攻击者在不需要任何口令的情况下直接批量获取所有用户信息。两个漏洞互为备份攻击者甚至可以二选一。从这里你就可以看出一套系统如果没有做好纵深防御问题之间是如何相互放大的。5.3 复盘之后的反向检查清单遇到同类系统的时候我现在会拿着这样一份清单去做反向检查这里也分享给读者文件下载/预览/上传接口参数里是否直接包含文件名、路径、URL这些参数经过路径规范化后是否严格限制在指定目录内所有涉及用户私有数据的查询接口请求参数里是否存在用户ID、订单号、文件ID等对象标识后端是否校验了对象归属管理端接口除了前端按钮隐藏后端有没有做角色/权限注释或拦截器校验换一个低权限账号重放请求能否成功/actuator系列端点、Druid监控页、Swagger文档页面是否对外开放测试环境代码里配置的数据库口令是否有残留系统日志/报错信息里会不会打印完整的SQL、请求参数、堆栈路径、服务器绝对路径每一条如果答案是“没有”或“不确定”都值得顺着往下挖一挖。这一套检查下来基本能把系统里目录遍历、越权、信息泄露的高发区扫了个七七八八。6. 防御体系搭建从单点加固到全局收敛单点修复能解决眼前的一个漏洞但如果不想每次安全测试都返工建立一套体系化的防御逻辑才是正路。这里我主要从安全设计的层面聊一聊如何把前面提到的三类漏洞从“被动堵漏”变成“主动设防”。6.1 输入与路径的标准化治理目录遍历的修复单点方案很多但从体系化的角度根本思路是两条一是路径白名单化二是资源ID化。路径白名单化意味着与其去写各种过滤规则和正则去对抗无穷无尽的编码绕过不如直接校验“解析后的完整路径是否以允许的基目录作为前缀”。Java里的标准做法是Path basePath Paths.get(/data/files/).toRealPath(); Path targetPath Paths.get(basePath.toString(), fileName).normalize(); if (!targetPath.startsWith(basePath)) { throw new SecurityException(非法路径访问); }注意这里一定要用toRealPath()解析掉所有符号链接和相对路径然后再做前缀判断。只做normalize()其实还不够因为攻击者可以利用系统内的符号链接来绕过目录限制。资源ID化则是更优雅的方案——用户在下载文件时不传文件名只传一个数据库里的文件ID后端根据ID查表拿到真实路径。这样用户完全接触不到文件路径也就谈不上穿越。这套方案在实际开发里更推荐但前提是文件表本身要做好权限控制否则攻击者可以通过遍历文件ID批量下载所有文件——绕过目录穿越但撞上了越权。这也再次印证了在复杂系统里没有“一招鲜”的防御每个环节都要联动。6.2 权限与身份的全局管控越权问题的体系化防御核心是把权限管理从“接口层”下沉到“数据层”。接口层的鉴权由Sa-Token、Spring Security这类框架统一处理通过注解或拦截器把每个接口对应的权限标识配置好。数据层的权限则需要在业务查询中统一追加数据范围条件。我见过一个相对成功的权限模型是这样设计的系统里有一个全局的CurrentUser注解任何接口需要操作数据时从当前会话中解析出当前用户实体而不是从前端参数里取身份信息。业务代码里的数据访问必须通过一个统一的DataPermissionService来包一层这个服务会在底层把当前用户可访问的组织、角色、数据范围自动拼接成SQL条件。这样一来开发人员基本不可能再写出“用户A能查用户B数据”的代码因为身份信息的获取不依赖参数数据范围又由统一组件兜底。6.3 泄露面收敛与监控响应信息泄露的收敛本质上是一个“暴露面管理”问题。从暴露面的视角看需要持续回答三个问题系统对外开放了哪些端口和端点这些端口和端点是否都是业务必须的如果被非授权人员访问到能看到什么敏感信息落地到具体行动上一方面是对中间件和框架的默认端点做“最小化”配置Actuator只开启必要的健康检查端点并加认证Swagger文档在预发环境关闭报错页面统一返回通用错误页不打印堆栈。另一方面是给敏感接口的访问行为增加监控和告警比如一个接口在短时间内被遍历大量ID参数或者在非工作时间收到大量来自同一IP的请求这些都应该能通过WAF或者日志分析平台感知到并进行拦截。SSL/TLS层面的信息泄露也是一样的思路。定期用扫描器检查对外开放的HTTPS服务确认密码套件的配置是否合理TLS版本是否足够新。即使业务系统因为历史原因暂时无法升级也要把弱套件的使用情况纳入监控——一旦发现某个服务开始使用弱套件且流量异常增长立刻就能定位到问题服务并做定向加固。最后说一点个人体会吧。目录遍历、越权、信息泄露这三类漏洞你说它们是“高危漏洞”吗从评分上看它们往往徘徊在中危和高危之间单独出现的杀伤力似乎并不惊人。但放在真实的业务系统里它们就像几块歪歪斜斜的积木——单独推倒任何一块都无伤大雅可一旦有人找到正确的顺序就能拼出一条通往核心资产的路径。我在写了这么多年的安全测试报告之后最大的一个感受是没有“小漏洞”只有被低估的影响。把每一个看着不起眼的路径参数、ID参数、调试端点都认真对待你会少踩很多坑也能在安全这条路上走得更稳。
返回列表