GeoServer 远程代码执行漏洞分析 (CVE-2024-36401)

GeoServer 远程代码执行漏洞分析 (CVE-2024-36401)

元亨-blckder02 中孚安全技术研究 2024-07-12 18:34

一、前言

官方公告:

https://github.com/geoserver/geoserver/security/advisories/GHSA-6jj6-gm7p-fcvv

https://github.com/geotools/geotools/security/advisories/GHSA-w3pj-wh35-fq8w

漏洞描述:

由于不安全地将属性名称评估为 XPath 表达式,多个 OGC 请求参数允许未经身份验证的用户通过针对默认 GeoServer 安装的特制输入进行远程代码执行 (RCE)。            GeoServer 调用的 GeoTools 库 API 会以不安全的方式将要素类型的属性名称传递给 commons-jxpath 库,该库在评估 XPath 表达式时可以执行任意代码。此 XPath 评估仅供复杂要素类型(即应用程序架构数据存储)使用,但也被错误地应用于简单要素类型,这使得此漏洞适用于所有GeoServer 实例。

影响版本:
GeoServer:           

< 2.23.6            

>= 2.24.0, < 2.24.4            

>= 2.25.0, < 2.25.2

二、环境搭建

源码下载:
https://github.com/geoserver/geoserver/archive/refs/tags/2.23.5.zip
           war下载:
https://sourceforge.net/projects/geoserver/files/GeoServer/2.23.5/geoserver-2.23.5-war.zip/download

配置好 Tomcat 和 debug 。        

启动 Tomcat,访问
http://127.0.0.1:8080/geoserver/web
,可以看到自带的图层数据,环境搭建成功。

三、漏洞复现

使用 GetPropertyValue 进行复现,POC:

service=wfs&version=2.0.0&request=GetPropertyValue&typeNames=sf:archsites&valueReference=exec(java.lang.Runtime.getRuntime(),'calc.exe')

或者:

POST /geoserver/wfs HTTP/1.1            
Host: 127.0.0.1:8080            
Content-Type: application/xml                     

<wfs:GetPropertyValue service='WFS' version='2.0.0'
xmlns:topp='http://www.openplans.org/topp'
xmlns:fes='http://www.opengis.net/fes/2.0'
xmlns:wfs='http://www.opengis.net/wfs/2.0'
valueReference='exec(java.lang.Runtime.getRuntime(),"calc.exe")'>
  <wfs:Query typeNames='topp:states'/>
</wfs:GetPropertyValue>

四. 漏洞分析

在第一个漏洞公告
中已经说明了可以通过WFS GetFeature、WFS GetPropertyValue、WMS GetMap、WMS GetFeatureInfo、WMS GetLegendGraphic 和 WPS Execute 请求利用此漏洞。           这些操作在《WFS参考》
文档中可以找到使用方法,本文复现使用的操作为 GetPropertyValue,作用如下:           

https://www.osgeo.cn/geoserver-user-manual/services/wfs/reference.html

就是从 typeNames 指定的图层中检索 valueReference 属性的值。GeoServer 调用的 GeoTools 库 API 会以不安全的方式将该属性传递给 commons-jxpath 库,该库在评估 XPath 表达式时就导致任意代码执行。

跟踪调试,从 Dispatcher.handleRequestInternal() 方法看起,处理请求逻辑。

跟进 findService() 方法,看到根据 id 和 version 选出了符合条件的 Service 对象。 

在 parseRequestKVP() 方法中,从 request 中获取了参数键值对,保存为 GetPropertyValueTypeImpl 对象。          

然后执行请求。

反射调用 getPropertyValue() 方法。           

跳到 DefaultWebFeatureService20.getPropertyValue(),实例化了一个 GetPropertyValue 对象,接着调用 GetPropertyValue.run()。           

跟进 FilterFactoryImpl.property(),实例化了一个 AttributeExpressionImpl 对象,将前端传入的
valueReference
参数值赋给了
this.attPath
。           

propertyName

propertyNameNoIndexes
都为 AttributeExpressionImpl 对象,调用 evaluate() 评估属性描述符,也就是评估这个 XPath 表达式,符合漏洞描述中所说的。           

跟进,调用 PropertyAccessors.findPropertyAccessors(),遍历找到可以处理当前评估操作的 PropertyAccessor 对象,获取到 FeaturePropertyAccessorFactory,正是第二个漏洞公告
中提到的利用方法。

然后调用 FeaturePropertyAccessorFactory.get(),传入
this.attPath
作为 XPath 表达式。
this.attPath
是前端传入的
valueReference
参数的值,也就是说这个位置的 XPath 表达式可控。

跟进,向
context
中注册了命名空间的名称及uri,然后迭代 XPath 指针。           

编译表达式,调用 compute() 进行计算。           


this.args
的计算转换后结果保存到
parameters
中,包含一个 Runtime对象和
calc.exe
字符串; 

然后获取到exec()
方法,调用该方法执行命令。

本文就简单跟踪一下命令执行的过程,更多细节及利用方式可参考:

https://xz.aliyun.com/t/14991

https://y4tacker.github.io/2024/07/03/year/2024/7/%E6%B5%85%E6%9E%90GeoServer-property-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%B3%A8%E5%85%A5%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C-CVE-2024-36401/

https://mp.weixin.qq.com/s?__biz=Mzg2MTc1NDAxMA==&mid=2247484076&idx=1&sn=4064cb6a006f5cc454b7fb982e8ab9c6