Why is this an issue?
Environment variable tampering occurs in a web application when it retrieves data like parameters or headers from an incoming HTTP request and uses
it to define the variables.
Depending on the controlled variable, an attacker could man-in-the-middle network requests or, in rare cases, achieve code execution.
What is the potential impact?
An attacker defines sensitive environment variables and can reach non-intended features or influence application execution flow. These environment
variables could be system defined or application-specific.
Examples of CVEs that resulted from this vulnerability were CVE-2017-17562 and CVE-2022-43781.
Below are some real-world scenarios that illustrate some impacts of an attacker exploiting the vulnerability.
LD_PRELOAD: Hijacking library functions
An attacker can upload a shared object to the web server and defines the LD_PRELOAD environment variable to ensure the shared object is loaded when
an arbitrary executable is run. In this malicious shared object, the attacker would overwrite a used function in the arbitrary executable and achieve
code execution.
HTTP_PROXY: Man-in-the-middle newtork requests
The web application runs an executable that respects the HTTP_PROXY environment variable. An attacker manipulates it to point to a reverse proxy
controlled by him and thus can sniff any sensitive data shared in web requests.
How to fix it in Java SE
Code examples
The following code is vulnerable to environment variable manipulation as it constructs the variables from untrusted data.
Noncompliant code example
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
Runtime r = Runtime.getRuntime();
String userInput = request.getParameter("example");
if (userInput != null) {
String[] envs = {userInput};
r.exec("/path/to/example", userInput);
} else{
r.exec("/path/to/example");
}
}
Compliant solution
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
Runtime r = Runtime.getRuntime();
String userInput = request.getParameter("example");
if (userInput != null && userInput.matches("^[a-zA-Z0-9]*$")) {
String[] envs = {"ENV_VAR=%s".format(userInput)};
r.exec("/path/to/example", envs);
} else {
r.exec("/path/to/example");
}
}
How does this work?
User input should be properly sanitized and validated, and ideally used only for the value of the environment variable. The environment variable
name should be statically defined.
Validation and sanitization could be done by restricting alphanumeric characters for the value and evaluating the name, if not statically defined,
against an allowlist of name values.
Resources
Standards