1 | 本文首发于奇安信攻防社区 https://forum.butian.net/article/749 |
环境搭建
https://geoserver.org/release/2.27.0/
去官网下载bin执行文件,并添加debug模式,也就是把下面的代码加到start.sh中就可以
1 | JAVA_OPTS="" |
漏洞成因
Geoserver未能正确处理GeoTools中的XML输入中的XSD引用,导致攻击者可以通过构造恶意的XSD文件,并远程进行加载,从而执行恶意操作。
漏洞分析
路由与功能点分析
首先还是先来分析一下他的路由,其实在环境搭建好,进入主页面的时候就可以发现他是进行了一个跳转的操作的,可以看到他源码的index.html中重定向到了web/路由。

因为是Geoserver是使用Servlet进行前后端交互的,直接到web.xml中查看他的规则。
首先是他的路由规则,他是通过Spring MVC的org.springframework.web.servlet.DispatcherServlet来进行GeoServer的请求分发的,这个Servlet会接收所以的Web请求,并根据Spring上下文定义的URL映射将请求分发给对应的控制器。

然后是他的业务逻辑

这里通过contextConfigLocation的上下文参数来指定配置文件位置,这里是applicationContext.xml文件和applicationSecurityContext.xml文件,这俩个文件一个是用于业务逻辑定义,另一个是用于安全设置,通过对这几个文件的搜索可以来进行业务逻辑判断。
然后这个文件里还有一些其他的功能的Listener和Filter,比如GeoServerContextLoaderListener负责加载和初始化上下文,这些就不一一分析了。
直接看org.springframework.web.servlet.DispatcherServlet类当中的doDispatch方法。

这个方法是所有Web请求的入口点,负责将处理器和拦截器链与Web请求相匹配,这里重点分析其中的getHandler方法。
1 | protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { |
这个方法会根据传入的HttpServletRequest来找到对应的HandlerExecutionChain,并返回可以处理该请求的处理器和拦截器链。其中handlerMappings是在初始化时从Spring的上下文中查找并收集的所有HandlerMapingBean,随后回到doDispatch。
当返回了相应的处理器和拦截器链之后,在doDispatch方法中将会执行handle方法,在这里会将控制权交给实际的业务逻辑处理器,从而进入实际的业务逻辑。
漏洞点分析
这个漏洞的触发点在org.geotools.xsd.Schemas类,这里从org.geotools.xsd.impl.ParserHandler#loadSchemas方法开始看。

这个方法是用于处理XSD文件的一个方法,其核心功能点在于根据XML 实例文档中提供的模式位置信息,加载所有相关的 XSD 文件,并构建一个可用于验证和查询的模式索引,其中schemas[i / 2] = Schemas.parse(location, locators, resolvers, uriHandlers);是用于处理 XSD文档加载并解析的一段代码。
跟进这个parse方法

这里主要是创建了一个ResouceSet,并将传入的参数注册到这个ResourceSet中,以便在后面的解析中使用。
然后再跟进到下一个parse方法

这个方法接收一个URL字符串(location)以及在上一个方法中配置过的ResoutceSet,并对XSD文档进行解析和加载。
这里要需要注意的有两个地方一个是对location的处理,这里对location进行了一系列处理操作,然后就将其加入了ResoutceSet中,并且没有对ResoutceSet有什么过滤的操作。
第二点就是触发点xsdMainResource.load(in, options);这里会执行XML解析,也就是触发点。
debug验证以及细节分析
知道了漏洞点以及路由规则现在开始构造payload并对其中的细节进行一些分析。
首先就是payload应该怎么构造,可以查看一下他的用户手册。

可以看到GetCapablits这一操作,这个操作会向WFS capabilities服务器发送请求,以获取该服务器支持的操作和服务或功能列表,重点看schemaLocation这一参数,这个参数指定XML文档所使用的XML Schema文件的位置,这个参数的第一个值为命名空间,第二值是该命名空间内需要加载的XSD文件。
这是一个服务器请求的操作,并且会远程加载指定的XSD文件,很自然的想到可以进行XXE攻击,我们将加载的XSD文件换成自己构造的恶意XSD就可以进行恶意请求,构造payload。
1 | <wfs:GetCapabilities |
构造的恶意.xsd文件如下
1 | <?xml version="1.0" encoding="UTF-8"?> |
wfs、wcs、wms那些路由都可以,发包。

首先会被DispatcherServlet拦截进行路由以及业务逻辑处理器分配

然后进入Dispatch,在这里进行请求处理,以及服务识别操作。

其中的service方法就是用于服务识别的

这里会识别出服务的类型是什么,并且在后续会根据识别出的服务类型进行执行操作,也就是dispatch方法。
随后进入parseRequestXML() 这个处理XML类型的数据的方法

随后一直跳转到startElement中调用loadSchemas方法的地方。

到了loadSchemas方法就和之前漏洞点分析的差不多了,通过调用parse方法一直到解析XML的地方。


至此分析完毕
漏洞验证
发送请求

本地起http服务被请求

dns服务器被请求

漏洞修复
厂商已发出新版本修复漏洞,更新至最新版本