跳转到帖子

新闻动态】GeoServer 零日攻击进入实战扫描:CVE-2026-76904 授权验证、日志排查与权限收敛

精选回复

发布于

背景

GeoServer 项目在 2026 年 9 月安全更新中披露,CVE-2026-76904 公开后数小时内即出现互联网扫描。该漏洞位于 GeoTools 对 OGC Filter 函数 jsonArrayContains 的 SQL 转换逻辑中,未经身份认证的请求可通过 WFS GetFeature、WMS GetMap 等接口影响后端 PostgreSQL/PostGIS。官方将其评为 Critical,CVSS 3.1 为 9.1。([github.com]( GeoServer 实例都能直接触发的通用 SQL 注入。实际风险需要同时满足:使用受影响版本、数据源为 PostgreSQL 12 及以上、已发布图层包含 String 或 JSON 字段,并且相关 WFS/WMS 服务可被攻击者访问。

以下操作仅适用于已取得书面授权的资产排查和漏洞验证。生产环境不建议直接发送破坏性 SQL,也不应使用延时、文件读取或命令执行语句验证。

问题定位

漏洞根因是 jsonArrayContains(<property>, '<jsonpath>', '<value>') 中的 value 参数进入生成 SQL 时未被正确转义。由于 OGC Filter 可通过 CQL_FILTER 参数或 XML fes:Filter 传入,攻击面不仅存在于管理后台,也可能直接暴露在公开地图查询接口上。([github.com]( GeoServer 3.0.1、2.28.5 和 2.27.6。2026 年 10 月 19 日发布的 3.0.2、2.28.6 已包含后续维护更新,仍在旧分支的实例应优先升级到当前受支持版本,而不是仅依赖反向代理特征拦截。([geoserver.org]( GeoServer 状态页、部署包 META-INF/MANIFEST.MF 或容器镜像标签,不要只依据 HTTP Server 头判断。

  • 确认数据源:在管理端检查 Store 类型是否为 PostGIS,并核对数据库主版本。
  • 确认触发条件:枚举已发布 FeatureType,检查是否包含 String、JSON 或 JSONB 字段。
  • 确认暴露面:分别检查 /geoserver/wfs、/geoserver/wms 及代理后的业务路径是否允许匿名访问。
  • 确认权限边界:审计 GeoServer 数据库账号是否拥有 superuser、pg_read_server_files、pg_write_server_files 或 pg_execute_server_program 等高危权限。
  • # 1. 非破坏性确认服务与版本线索
    curl -sk ' \
      -o /tmp/wfs-capabilities.xml
    
    grep -Eio 'GeoServer[^<]*|version="[0-9.]+"' /tmp/wfs-capabilities.xml | head
    
    # 2. 检查本地部署包版本
    unzip -p /opt/tomcat/webapps/geoserver.war META-INF/MANIFEST.MF \
      | grep -Ei 'version|build|implementation'
    
    # 3. PostgreSQL 版本与当前连接身份
    psql -d gisdb -c 'SELECT version(), current_user;'
    
    # 4. 检查 GeoServer 数据库角色的关键权限
    psql -d gisdb -c "
    SELECT r.rolname,
           r.rolsuper,
           r.rolcreaterole,
           r.rolcreatedb,
           r.rolreplication,
           pg_has_role(r.rolname, 'pg_read_server_files', 'member') AS read_server_files,
           pg_has_role(r.rolname, 'pg_write_server_files', 'member') AS write_server_files,
           pg_has_role(r.rolname, 'pg_execute_server_program', 'member') AS execute_program
    FROM pg_roles r
    WHERE r.rolname = 'geoserver_app';"
    
    # 5. 检查数据库中可能满足触发条件的字符及 JSON 字段
    psql -d gisdb -c "
    SELECT table_schema, table_name, column_name, data_type
    FROM information_schema.columns
    WHERE table_schema NOT IN ('pg_catalog','information_schema')
      AND data_type IN ('character varying','text','json','jsonb')
    ORDER BY table_schema, table_name;"

    漏洞确认应优先采用“版本、组件条件、补丁状态”三项证据闭环。若必须进行动态验证,建议在隔离测试副本中使用只读数据库账号,并以普通合法 jsonArrayContains 查询作为基线,观察修复前后的 SQL 绑定方式和错误响应差异,不要在生产库中尝试引号闭合、堆叠查询或延时函数。

    日志排查

    GeoServer 默认运行日志通常位于 GEOSERVER_DATA_DIR/logs/geoserver.log,具体记录粒度取决于 Server Settings 中选择的日志配置。Web 容器访问日志、反向代理日志和 PostgreSQL 日志需要联合检查,仅查询 GeoServer 应用日志容易漏掉被代理层拦截或数据库已执行的请求。([docs.geoserver.org]( Nginx/Tomcat:查找直接出现或经过 URL 编码的函数名 zgrep -Eai 'jsonArrayContains|jsonarraycontains|CQL_FILTER|CQL_FILTER%3[Dd]|GetFeature|GetMap' \ /var/log/nginx/access.log* /opt/tomcat/logs/localhost_access_log.* 2>/dev/null # GeoServer 应用日志:关注过滤器解析、SQL 和异常栈 zgrep -Eai 'jsonArrayContains|CQL|Filter|SQLException|PSQLException|syntax error|JDBC' \ "$GEOSERVER_DATA_DIR"/logs/geoserver.log* 2>/dev/null # PostgreSQL:重点检查异常函数、文件访问及长时间查询 zgrep -Eai 'jsonArrayContains|pg_read_file|pg_ls_dir|COPY.*PROGRAM|syntax error|statement:' \ /var/log/postgresql/postgresql-*.log* 2>/dev/null # 当前可疑会话,仅用于应急观察 psql -d gisdb -c " SELECT pid, usename, client_addr, application_name, now() - query_start AS runtime, state, left(query, 300) AS query FROM pg_stat_activity WHERE datname = current_database() AND state <> 'idle' ORDER BY query_start;"

    排查时不要只搜索单一漏洞函数名。攻击流量可能经过 URL 编码、POST XML、大小写变化或代理转写。应同时关联同一源地址的 WFS/WMS 请求量、4xx/5xx 突增、数据库语法错误、异常长查询,以及 GeoServer Java 进程对外建立的新连接。

    内网攻防链路与权限边界

    SQL 注入后的影响由数据库角色权限决定。如果 GeoServer 使用 postgres 超级用户连接,攻击面可能从数据读取扩大到服务端文件访问,甚至借助数据库高权限能力触及操作系统。官方特别提醒,应避免为应用连接账号授予 pg_read_file 等能力,也不应沿用默认 PostGIS 镜像中的高权限账号配置。([github.com]( 使用独立登录角色,只授予业务 schema 的 SELECT 权限;确需编辑功能时,再按表单独增加 INSERT、UPDATE、DELETE。

  • 系统层:PostgreSQL 与 GeoServer 使用不同低权限系统账号,禁止共享可写目录。
  • 网络层:数据库仅接受 GeoServer 应用节点访问,禁止 PostGIS 主机主动访问办公网、域控及运维网段。
  • 密钥层:数据库连接密码不要复用于 SSH、容器仓库、管理后台或域账号。
  • 监控层:对 Java、postgres 进程发起的异常 DNS、HTTP、SMB 和 LDAP 连接建立告警。
  • 临时处置与修复

    无法立即升级时,可暂时关闭非必要 WFS/WMS 服务,或在反向代理层限制来源。仅拦截 jsonArrayContains 字符串并不可靠,因为 POST XML、编码和语法变形都可能绕过,它只能作为短时止血措施。

    # PostgreSQL:撤销应用角色不应具备的高危成员关系
    REVOKE pg_read_server_files FROM geoserver_app;
    REVOKE pg_write_server_files FROM geoserver_app;
    REVOKE pg_execute_server_program FROM geoserver_app;
    
    # 禁止连接角色继承意外权限,并限制数据库连接
    ALTER ROLE geoserver_app NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION;
    ALTER ROLE geoserver_app CONNECTION LIMIT 20;
    
    # Nginx 临时限制示例:仅允许受信网段访问 WFS
    location = /geoserver/wfs {
        allow 10.20.0.0/16;
        allow 192.168.50.0/24;
        deny all;
        proxy_pass 
    }
    • 升级 GeoServer 至 3.0.1、2.28.5、2.27.6 或更高的受支持安全版本。
    • 升级后重新检查实际加载的 GeoTools JAR,防止旧文件残留在 WEB-INF/lib 或共享 Tomcat classpath。
    • 轮换 GeoServer 数据源密码,并检查同密码是否被其他服务复用。
    • 将 GeoServer、Tomcat、PostgreSQL 和反向代理日志集中保存,确保时间同步和源地址字段完整。
    • 若发现疑似恶意 SQL、异常文件访问或数据库进程外连,应按已失陷事件处理,而不是仅完成补丁升级。

    总结

    CVE-2026-76904 的处置重点不是复现一条 SQL 注入语句,而是确认“公开 OGC 接口、受影响版本、PostGIS 字段条件、数据库角色权限”是否形成完整攻击链。对授权测试团队而言,版本与配置验证足以判断漏洞成立;对防守方而言,升级只是第一步,还需要同步收敛数据库账号权限、补齐 WFS/WMS 访问日志,并追查 Java 与 PostgreSQL 进程是否出现异常外连或文件访问行为。

    网络流量与边界分析示意图
    网络请求、日志与边界流量分析示意
    安全事件影响分析示意图
    安全动态、影响面和处置建议示意

    这个编号和具体受影响版本建议先以 GeoServer 官方公告、NVD/CNVD 记录为准,暂时不要只根据扫描器的 CVE 名称判断是否已修复。对于已经出现实战扫描的环境,建议先做三件事:

    1. 确认暴露面:公网通常不应直接暴露 GeoServer REST 管理接口。重点检查 /geoserver/rest/、/geoserver/web/ 以及 WMS/WFS 服务是否被反向代理放行。
    2. 核对访问结果:重点筛选来自公网的 REST 请求,尤其是返回 200、较大响应体,或短时间内连续出现 401/403 后转为 200 的源地址。仅看 404 不够,扫描器经常会根据响应差异判断部署状态。
    3. 检查权限边界:确认匿名用户没有写入、配置修改或工作区管理权限;REST API 最好只允许跳板机、管理网段或本机访问,而不是依赖弱口令和登录页保护。

    如果是 Nginx 反代,可以先临时收紧管理接口,例如:

    location ^~ /geoserver/rest/ {
        allow 10.10.0.0/16;
        allow 192.168.50.0/24;
        deny all;
    
        proxy_pass 
    }
    
    location ^~ /geoserver/web/ {
        allow 10.10.0.0/16;
        deny all;
    
        proxy_pass 
    }

    日志排查不要只搜 CVE 编号,可以按 URI、方法和状态码组合检索。以 Nginx 访问日志为例:

    awk '$7 ~ /\/geoserver\/(rest|web)/ {print}' /var/log/nginx/access.log
    
    grep -Ei '\/geoserver\/(rest|web)|POST|PUT|DELETE' \
        /var/log/nginx/access.log | tail -n 500
    
    awk '$9 ~ /200|201|204/ && $7 ~ /\/geoserver\/(rest|web)/ {print}' \
        /var/log/nginx/access.log

    同时核对 GeoServer 数据目录和应用服务器日志的修改时间,特别关注 workspaces、layers、datastores、安全配置文件以及新增的样式、模板或外部数据源。若发现异常成功请求,建议立即保留原始日志、反代日志和主机时间线,再进行版本升级或替换,不要先清理现场。

    最后,升级后应从外部网络复测:未授权访问应返回 401/403,管理接口不应因路径变形、尾部斜杠、编码或 HTTP 方法变化而绕过限制;业务所需的 WMS/WFS 公开接口则单独做最小权限和速率限制,避免为了封堵管理面而误伤正常地图服务。

    最近浏览 0

    • 没有会员查看此页面。