本仓库包含对在 GeoServer 平台和 GeoTools 库中发现的 SQL 注入漏洞的详细描述和复现步骤。该漏洞已被分配标识符 CVE-2023-25157(针对 GeoServer)和 CVE-2023-25158(针对 GeoTools)。
GeoServer 是一个用 Java 编写的开源软件服务器,提供查看、编辑和共享地理空间数据的能力。它旨在成为一种灵活、高效的解决方案,用于分发来自地理信息系统(GIS)数据库、基于网络的数据和个人数据集等各种来源的地理空间数据。
GeoServer 遵循开放地理空间联盟(OGC)的数据共享标准,包括 Web 要素服务(WFS)、Web 地图服务(WMS)和 Web 覆盖服务(WCS)。这种对标准的遵循意味着来自 GeoServer 的数据可以用于各种各样的应用程序,从定制构建的 GIS 软件到现成的解决方案。
GeoServer 主要基于 Spring Framework 构建,但同时也使用了许多其他库和框架,包括:
GeoTools: 一个开源 Java 库,为地理空间数据提供工具。GeoServer 在许多核心功能(如数据读取、写入和转换)中使用 GeoTools。所讨论的漏洞深深嵌入在开放地理空间联盟(OGC)标准定义的过滤器和函数表达式中。这些表达式构成了地理空间数据查询和操作的骨干,在 GeoServer 和 GeoTools 等系统的功能中发挥着关键作用。
当这些漏洞被利用时,可能导致严重的安全破坏。未经授权的信息泄露是首要问题,因为攻击者可能访问数据库中存储的敏感数据。未经授权的修改是另一个潜在后果,攻击者能够以对自己有利的方式篡改数据。此外,这些漏洞还可能助长服务中断,成功的利用有可能导致服务不可用。
以下内容对每个已识别的漏洞进行了深入分析。每个漏洞都被详细探讨,讨论了其具体特征、导致其显现的条件以及利用它的潜在影响。以下是针对 GeoServer 发现的漏洞的详细分解:
PropertyIsLike 过滤器:当 PropertyIsLike 过滤器与 String 字段配合使用,并结合任何基于关系数据库的 Store、启用了编码函数的 PostGIS DataStore,或任何将索引存储在关系数据库中的影像镶嵌数据集时,存在此漏洞。strEndsWith 函数:当 strEndsWith 函数与启用了编码函数的 PostGIS DataStore 一起使用时,会出现此漏洞。strStartsWith 函数:当 strStartsWith 函数与启用了编码函数的 PostGIS DataStore 一起使用时,会发现此漏洞。FeatureId 过滤器:当 FeatureId 过滤器与任何具有 String 主键列的数据库表一起使用,并且预编译语句(prepared statements)被禁用时,存在此漏洞。jsonArrayContains 函数:当 jsonArrayContains 函数与 String 或 JSON 字段以及 PostGIS 或 Oracle DataStore 一起使用时,会发现此漏洞(仅在 GeoServer 2.22.0 及更高版本中)。DWithin 过滤器:当 DWithin 过滤器与 Oracle DataStore 一起使用时,会发现此漏洞。以下是针对 GeoTools 发现的漏洞的详细分解:
PropertyIsLike 过滤器:
strEndsWith 函数:
strStartsWith 函数:
FeatureId 过滤器:
jsonArrayContains 函数:
DWithin 过滤器:
CVE-2023-25157 GeoServer SQL 注入 漏洞影响。CVE-2023-25158 GeoTools SQL 注入 漏洞影响。对于 GeoServer SQL 注入(CVE-2023-25157)和 GeoTools SQL 注入(CVE-2023-25158)漏洞,建议采取的行动是升级到上述引用的版本或更高版本。如果已完成此升级,则无需额外步骤。但是,对于那些可能难以立即升级的用户,Geo 团队在下方提供了一些替代解决方案。
禁用 PostGIS Datastore 的 encode functions(编码函数)设置,以缓解 strEndsWith、strStartsWith 漏洞(like 过滤器没有缓解措施,如果已发布的要素类型中存在字符串字段)。
启用 PostGIS DataStore 的 preparedStatements(预编译语句)设置,以缓解 FeatureId 漏洞。```java
Map<String, Object> params = new HashMap < >();
params.put("dbtype", "postgis");
params.put("host", "localhost");
params.put("port", 5432);
params.put("schema", "public");
params.put("database", "database");
params.put("user", "postgres");
params.put("passwd", "postgres");
params.put("preparedStatements", true); // mitigation
params.put("encode functions", false); // mitigation
DataStore dataStore = DataStoreFinder.getDataStore(params);
- 作为限制攻击面的良好实践,务必为连接池所使用的数据库账户授予最低所需的权限级别(例如,除非使用了 WFS-T/importer/REST granule harvesting,否则仅授予只读权限;访问权限仅限制在生产使用所需的 schema 和表上)
- `PropertyIsLike` 过滤器目前没有可用的缓解措施;在您能够升级之前,可以选择禁用数据库 DataStore。
- 对于 Oracle DataStore 上的 `DWithin`,目前没有可用的缓解措施;在您能够升级之前,可以选择禁用 Oracle DataStore。
### <b>补丁分析:GitHub Issue 及相关提交</b>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
下方提供了与在 GeoServer 和 GeoTools 中发现的 SQL 注入漏洞相关的若干 JIRA 问题链接。通过这些链接,您可以访问与这些特定漏洞相关的关键数据、讨论内容以及提议的解决方案。
- [GEOS-10842: JDBCConfig: escape user inputs in SQL queries](https://osgeo-org.atlassian.net/browse/GEOS-10842)
- [GEOS-10839: JDBCConfig: add JDBC Configuration parameter to disable SQL comments and pretty-printing](https://osgeo-org.atlassian.net/browse/GEOS-10839)
- [GEOT-7302: Escape user inputs in SQL queries](https://osgeo-org.atlassian.net/browse/GEOT-7302)
查看 [`geoserver/geoserver@145a8af`](https://github.com/geotools/geotools/commit/64fb4c47f43ca818c2fe96a94651bff1b3b3ed2b) 提交时,可以清楚地看到以下各自的更改:
- 在 [`ConfigDatabase.java`](https://github.com/geoserver/geoserver/blob/b05287608048d0f6e36c264f43fe15aa5dfb5130/src/community/jdbcconfig/src/main/java/org/geoserver/jdbcconfig/internal/ConfigDatabase.java) 中,新增了一个属性字段,并修改了构造函数以纳入该属性字段。这样可以更灵活地定制数据库配置,并有可能增强安全措施。[`NamedParameterJdbcTemplate`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.html) 是 Spring Framework 提供的一个类,它支持使用命名参数来编写 JDBC 语句,而不是使用经典的占位符('?')参数来编写 JDBC 语句。在该提交中,`ConfigDatabase` 构造函数已更新为接受一个 `DataSource`,并据此创建一个 `NamedParameterJdbcTemplate`。命名参数提高了可读性,还能防止 SQL 注入攻击,因为它们清楚地表明参数是参数化的,而不是 SQL 命令的一部分。
> [src/community/jdbcconfig/src/main/java/org/geoserver/jdbcconfig/internal/ConfigDatabase.java](https://github.com/geoserver/geoserver/commit/145a8af798590288d270b240235e89c8f0b62e?diff=split#diff-1b49bc6af3f36da2ebf7a0d8d3af3fa3697ccee91bf67a690f99837ee2730bed)```java
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.jdbcconfig.internal;
// import some packages...
import org.geoserver.jdbcloader.JDBCLoaderProperties;
public class ConfigDatabase implements ApplicationContextAware {
public static final Logger LOGGER = Logging.getLogger(ConfigDatabase.class);
private static final int LOCK_TIMEOUT_SECONDS = 60;
private Dialect dialect;
private JDBCLoaderProperties properties;
// rest of the codebase
protected ConfigDatabase() {
//
}
public ConfigDatabase(
JDBCLoaderProperties properties,
DataSource dataSource,
XStreamInfoSerialBinding binding) {
this(properties, dataSource, binding, null);
}