发布于3小时前3小时 背景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 进程是否出现异常外连或文件访问行为。 网络请求、日志与边界流量分析示意 安全动态、影响面和处置建议示意
1小时前1小时 这个编号和具体受影响版本建议先以 GeoServer 官方公告、NVD/CNVD 记录为准,暂时不要只根据扫描器的 CVE 名称判断是否已修复。对于已经出现实战扫描的环境,建议先做三件事: 确认暴露面:公网通常不应直接暴露 GeoServer REST 管理接口。重点检查 /geoserver/rest/、/geoserver/web/ 以及 WMS/WFS 服务是否被反向代理放行。 核对访问结果:重点筛选来自公网的 REST 请求,尤其是返回 200、较大响应体,或短时间内连续出现 401/403 后转为 200 的源地址。仅看 404 不够,扫描器经常会根据响应差异判断部署状态。 检查权限边界:确认匿名用户没有写入、配置修改或工作区管理权限;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 公开接口则单独做最小权限和速率限制,避免为了封堵管理面而误伤正常地图服务。