
Laboratorio local de GeoServer/PostGIS que reproduce la inyección SQL de OGC Filter (CVE-2023-25157/25158) con modos de prueba A/B vulnerable, parcheado y mitigado.
Este lab utiliza GeoServer/PostGIS para investigar la inyección SQL en filtros OGC en un entorno local, con separación clara entre el modo operador/setup y el modo atacante.
GeoServer 2.22.0 incluye GeoTools vulnerable. GeoServer 2.22.2 incluye GeoTools parcheado. El lab mantiene el mismo esquema/solicitud para pruebas A/B de versión, mitigación y límite de privilegios.
| Modo | Superficie | Propósito |
|---|
| Setup/operator REST | contenedor interno cve-operator | Configuración REST, validación y revisión de logs del backend |
| Gateway único | 127.0.0.1:8889 | Un único puerto para la UI del operador y las rutas OWS |
| UI Web del operador | 127.0.0.1:8889/geoserver/web/ | UI de GeoServer para el operador; con proxy Basic Auth |
| Atacante vulnerable | 127.0.0.1:8889/vuln/geoserver/ows | WFS/OWS vulnerable, errores de BD visibles en la respuesta |
| Atacante parcheado | 127.0.0.1:8889/patched/geoserver/ows | GeoServer 2.22.2 / GeoTools 28.2 |
| Atacante realista | 127.0.0.1:8889/realistic/geoserver/ows | WFS/OWS vulnerable pero el gateway elimina el detalle del error |
| Mitigación function | 127.0.0.1:8889/mit-functions/geoserver/ows | GeoServer 2.22.0, encode functions=false |
| Mitigación FeatureId | 127.0.0.1:8889/mit-featureid/geoserver/ows | GeoServer 2.22.0, preparedStatements=true |
PostgreSQL/PostGIS no publica puertos al host. GeoServer no publica directamente el puerto 8080 al host; el host solo ve cve-gateway en 127.0.0.1:8889. El contenedor cve-attacker solo está en attacker-net; no tiene ruta hacia PostgreSQL ni al servicio interno de GeoServer. La configuración REST pasa por el contenedor interno cve-operator en geoserver-net.
Abrir en el navegador:
http://127.0.0.1:8889/geoserver/web/
Inicio de sesión en 2 capas:
operator / operator_labadmin / geoserverTodo pasa por el mismo gateway 8889, sin necesidad de recordar múltiples puertos. Burp puede mantener el proxy predeterminado 127.0.0.1:8080.
.\lab.ps1 reset all
.\lab.ps1 validate
powershell -ExecutionPolicy Bypass -File .\verify-lab.ps1
powershell -ExecutionPolicy Bypass -File .\negative-controls.ps1
powershell -ExecutionPolicy Bypass -File .\attack-chain.ps1
Comandos de gestión:
.\lab.ps1 start vulnerable
.\lab.ps1 start patched
.\lab.ps1 start mitigated
.\lab.ps1 start worstcase
.\lab.ps1 reset all
.\lab.ps1 stop
.\lab.ps1 status
Tablas seed:
cities: clave primaria entera, columna name de tipo text, usada para strStartsWith/strEndsWith.sensors_text: clave primaria text, usada para inyección FeatureId.sensors_int: clave primaria entera, control negativo para FeatureId.events: capa de investigación JSONB.internal_assets: no publicada, contiene LAB-CANARY-<UUID> nuevo tras cada reset.local_points: shapefile no-JDBC, control negativo.Roles:
geoserver_readonly: CONNECT, USAGE en el esquema, SELECT solo en tablas publicadas.geoserver_impact: SELECT adicional sobre internal_assets para ilustrar un usuario de BD de aplicación con permisos amplios.geoserver_worstcase: perfil separado, con pg_read_server_files para leer el archivo canary falso /lab/flag.txt.attack-chain.ps1 realiza:
GetCapabilities.DescribeFeatureType.encode functions=false.preparedStatements=true.internal_assets, la rama impact filtra el canary, y parcheado/realista no revelan el canary.La evidencia se guarda en evidence/attack-chain-*. La carpeta actual solo conserva la evidencia del último pase exitoso para evitar desorden.
Este perfil no forma parte del escenario principal:
.\lab.ps1 start worstcase
powershell -ExecutionPolicy Bypass -File .\worstcase-demo.ps1
Solo lee el archivo canary falso /lab/flag.txt, no lee /etc/passwd, no hace dump de hashes, no crackea contraseñas.