文章总结: 文档分析了SupermapiServer历史漏洞的成因与利用手法,指出因Shiro鉴权缺失及OutputPathHandler处理器对转发请求过滤不足,导致通过/output/…/路径可未授权读取WEB-INF等敏感文件。漏洞利用TomcatForward机制绕过StandardContextValve检测,并结合数据库文件获取系统Token。文中还探讨了Forward在文件读取与鉴权绕过的实战利用面及WAF绕过思路,最后提及相关代码审计课程内容。 综合评分: 82 文章分类: 漏洞分析,WEB安全,代码审计,红队,实战经验
Supermap iServer历史漏洞浅析(上)
原创
路人甲 路人甲
红细胞安全实验室
2026年3月30日 11:50 广东
在小说阅读器读本章
去阅读
漏洞复现
GET /iserver/output/../WEB-IN%2546/iserver-system.xml HTTP/1.1
Host: 127.0.0.1:8090
该请求主要获取supermap配置文件,还需搭配iserver-security.db来获取supermap数据库当中的管理员用户名(非固定,由用户自定义设置),组合起来即可获取目标系统Token
漏洞原理
首先是为什么这个路由可以未授权访问,supermap基于Shiro进行鉴权,当中shirourls.ini中并没有针对于/**的全局规则,故可以未授权访问
导致本次漏洞的主要原因是com.supermap.server.host.webapp.handlers.OutputPathHandler这个处理器
在这里判断以/output开头则会解码并使用Forward转发请求,转发的路由是解码后的路由,之所以可以转发读取文件有两个原因
- • Tomcat虽然存在
org.apache.catalina.core.StandardContextValve这个Valve检测不能读取WEB-INF、META-INF等特殊目录下的文件,不过Forward转发请求的时候不过Valve,最多过filter
- • 没有配置了
DispatcherType带有Forward的Filter二次过滤,默认Filter的DispatcherType值为REQUEST
如下图所示可以看到这里getDispatcher底层会进行类似正常的路由匹配流程,解码并匹配Wrapper(Servlet在Tomcat容器内部的概念)
getRequestDispatcher:440, ApplicationContext (org.apache.catalina.core)
getRequestDispatcher:215, ApplicationContextFacade (org.apache.catalina.core)
getRequestDispatcher:1309, Request (org.apache.catalina.connector)
getRequestDispatcher:462, RequestFacade (org.apache.catalina.connector)
handle:36, OutputPathHandler (com.supermap.server.host.webapp.handlers)
process:204, AbstractHandler (com.supermap.server.host.webapp.handlers)
a:233, AbstractHandler (com.supermap.server.host.webapp.handlers)
invokeLowerPriorityHandlers:220, AbstractHandler (com.supermap.server.host.webapp.handlers)
process:206, AbstractHandler (com.supermap.server.host.webapp.handlers)
process:325, BasicHandler (com.supermap.server.host.webapp.handlers)
doFilter:254, ApplicationFilter (com.supermap.server.host.webapp)
internalDoFilter:168, ApplicationFilterChain (org.apache.catalina.core)
doFilter:144, ApplicationFilterChain (org.apache.catalina.core)
doFilter:40, TunnelFilter (com.supermap.services.filter)
internalDoFilter:168, ApplicationFilterChain (org.apache.catalina.core)
doFilter:144, ApplicationFilterChain (org.apache.catalina.core)
handleNonCORS:333, CorsFilter (org.apache.catalina.filters)
doFilter:160, CorsFilter (org.apache.catalina.filters)
internalDoFilter:168, ApplicationFilterChain (org.apache.catalina.core)
doFilter:144, ApplicationFilterChain (org.apache.catalina.core)
doFilter:129, HttpHeaderSecurityFilter (org.apache.catalina.filters)
internalDoFilter:168, ApplicationFilterChain (org.apache.catalina.core)
doFilter:144, ApplicationFilterChain (org.apache.catalina.core)
invoke:168, StandardWrapperValve (org.apache.catalina.core)
invoke:90, StandardContextValve (org.apache.catalina.core)
invoke:482, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:130, StandardHostValve (org.apache.catalina.core)
invoke:93, ErrorReportValve (org.apache.catalina.valves)
invoke:74, StandardEngineValve (org.apache.catalina.core)
service:346, CoyoteAdapter (org.apache.catalina.connector)
service:396, Http11Processor (org.apache.coyote.http11)
process:63, AbstractProcessorLight (org.apache.coyote)
process:937, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1793, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:52, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1190, ThreadPoolExecutor (org.apache.tomcat.util.threads)
run:659, ThreadPoolExecutor$Worker (org.apache.tomcat.util.threads)
run:63, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:750, Thread (java.lang)
通过前面操作完成了路由匹配,也就是找Servlet这个步骤,这里由于没有处理它的Servlet所以会使用默认的Servlet,也就是org.apache.catalina.servlets.DefaultServlet(该servlet用于读取磁盘上的文件),以上便是getDispatcher底层逻辑,接下来就是forward请求转发了
主要逻辑位于org.apache.catalina.core.ApplicationDispatcher#doForward方法里面
设置各种属性信息并继续调用processRequest处理请求
匹配适用的Filter链组成过滤链并和Wrapper包装在一起,本质上就是Tomcat底层那套Filter责任链
前面之所以说想要文件读取还需要没有DispatcherType带有Forward的Filter二次过滤导致无法读取的原因也就是在这,在org.apache.catalina.core.ApplicationFilterFactory#createFilterChain方法构建Filter链的时候有个关键判断,也就是这里的matchDispatcher
这个属性在前面的forward方法调用里设置的
认DispatchType为REQUEST,也就是无法过滤Forward请求,进而导致文件读取
Forward利用面
在真实场景下Forward可能存在如下利用面:
- • 文件读取(需要类似本次漏洞一样二次解码转发的场景,之所以需要二次解码是因为直接访问的话默认
Tomcat会解码一次,解码一次后处理流程走到StandardContextValve的时候判断不通过) - • 鉴权绕过:利用请求转发去请求被
Filter过滤的一些敏感接口
影响Forward利用的主要因素有如下:
- • 多套过滤机制:在实战场景可能碰到既有
Filter过滤又有SpringAOP或者SpringInterceptor过滤的场景,这时候能否利用成功还得看后面的SpringAOP或者SpringInterceptor过滤代码,因为这两个过滤在请求转发处理之后处理的 - • 配置
Forward DispatcherType的Filter:配置该DispatcherType的Filter在请求转发的场景仍然生效,例如如下Filter
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
思考
该漏洞在实战中有较为明显的/../跨目录特征,基本会被WAF拦截,有没有什么好办法绕过呢?
最后
本文当中所提及内容均来自实战代码审计班课程内容,关于该产品更加深入利用手法可以咨询课程
顺便再推荐一下我师傅的代码审计课程。近期某统一认证产品的课程章节已结束,马上开启某报表的章节,感兴趣的朋友可以尽快加入。课程中包含各类产品最新补丁对应的 0day 漏洞(非水洞) 的挖掘与分析;过往课程也涵盖多款市面产品的 0day / 1day / nday 漏洞案例讲解。课程后续会持续更新推进,支持一次报名长期学习与答疑。适合真正对代码审计感兴趣、或想系统学习但缺少思路与方法体系的同学(如有其他目的请勿打扰)。对基础要求不高,能读懂代码即可,真正帮助你从只能读懂代码到找到问题。个人学习过程中受益良多,特此分享推荐给希望提升自己的朋友(非广告)。若有打扰,敬请见谅。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:红细胞安全实验室 路人甲 路人甲《Supermap iServer历史漏洞浅析(上)》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论