
Labo GeoServer/PostGIS local reproduisant l'injection SQL OGC Filter (CVE-2023-25157/25158) avec des modes de test A/B vulnérable, corrigé et atténué.
Ce lab utilise GeoServer/PostGIS pour étudier l'injection SQL via OGC Filter dans un environnement local, avec une séparation claire entre le mode opérateur/setup et le mode attaquant.
GeoServer 2.22.0 intègre GeoTools vulnérable. GeoServer 2.22.2 intègre GeoTools corrigé. Le lab conserve le même schéma/requête pour un test A/B des versions, de la mitigation et de la frontière de privilèges.
| Mode | Surface | Objectif |
|---|
| Setup/operator REST | conteneur interne cve-operator | Configuration REST, validation et revue des logs backend |
| Passerelle unique | 127.0.0.1:8889 | Un seul port pour l'UI opérateur et les routes OWS |
| Operator Web UI | 127.0.0.1:8889/geoserver/web/ | UI GeoServer pour l'opérateur ; avec proxy Basic Auth |
| Attacker vulnerable | 127.0.0.1:8889/vuln/geoserver/ows | WFS/OWS vulnérable, erreurs DB visibles dans la réponse |
| Attacker patched | 127.0.0.1:8889/patched/geoserver/ows | GeoServer 2.22.2 / GeoTools 28.2 |
| Attacker realistic | 127.0.0.1:8889/realistic/geoserver/ows | WFS/OWS vulnérable mais la passerelle supprime les détails d'erreur |
| Mitigation function | 127.0.0.1:8889/mit-functions/geoserver/ows | GeoServer 2.22.0, encode functions=false |
| Mitigation FeatureId | 127.0.0.1:8889/mit-featureid/geoserver/ows | GeoServer 2.22.0, preparedStatements=true |
PostgreSQL/PostGIS ne publie aucun port vers l'hôte. GeoServer ne publie pas directement le port 8080 vers l'hôte ; l'hôte ne voit que cve-gateway sur 127.0.0.1:8889. Le conteneur cve-attacker est uniquement sur attacker-net ; il n'a aucune route vers PostgreSQL ni vers le service interne GeoServer. La configuration REST passe par le conteneur interne cve-operator sur geoserver-net.
Ouvrir dans le navigateur :
http://127.0.0.1:8889/geoserver/web/
Connexion à 2 niveaux :
operator / operator_labadmin / geoserverTout passe par la même passerelle 8889, pas besoin de mémoriser plusieurs ports. Burp peut conserver le proxy par défaut 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
Commandes de gestion :
.\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
Tables seed :
cities : clé primaire entière, colonne name de type text, utilisée pour strStartsWith/strEndsWith.sensors_text : clé primaire text, utilisée pour l'injection FeatureId.sensors_int : clé primaire entière, contrôle négatif pour FeatureId.events : couche de recherche JSONB.internal_assets : non publiée, contient LAB-CANARY-<UUID> à chaque reset.local_points : contrôle négatif shapefile non-JDBC.Rôles :
geoserver_readonly : CONNECT, USAGE sur le schéma, SELECT uniquement sur les tables publiées.geoserver_impact : SELECT supplémentaire sur internal_assets pour illustrer un utilisateur DB applicatif aux droits trop larges.geoserver_worstcase : profil séparé, avec pg_read_server_files pour lire le fichier canary factice /lab/flag.txt.attack-chain.ps1 effectue :
GetCapabilities.DescribeFeatureType.encode functions=false.preparedStatements=true.internal_assets, que la branche impact fuit le canary, et que patched/realistic ne divulguent pas le canary.Les preuves sont enregistrées dans evidence/attack-chain-*. Le dossier ne conserve que les preuves de la dernière exécution réussie pour éviter l'encombrement.
Ce profil ne fait pas partie du scénario principal :
.\lab.ps1 start worstcase
powershell -ExecutionPolicy Bypass -File .\worstcase-demo.ps1
Il ne lit que le fichier canary factice /lab/flag.txt, ne lit pas /etc/passwd, ne dump aucun hash, ne casse aucun mot de passe.