April 3, 2020

GHSL-2020-011: Remote Code Execution - JavaEL Injection (low privileged accounts) in Nexus Repository Manager

Alvaro Muñoz

Summary

Remote Code Execution - JavaEL Injection (low privileged accounts)

CVE

CVE-2020-10199

Product

Nexus Repository Manager

Tested Version

3.20.1

Details

It is possible for any authenticated user, no matter the permissions granted, to run arbitrary code on the server (with Nexus process privileges) by injecting arbitrary Java Expression Language (EL) expressions.

We conducted a CodeQL-based variant analysis of CVE-2018-16621 and found that the applied mitigation (stripJavaEL()) was not applied to org.sonatype.nexus.validation.ConstraintViolationFactory. Therefore when user-controlled data flows into createViolation(final String path, final String message) it will get evaluated as a Java EL by buildConstraintViolationWithTemplate():

  private static class HelperValidator extends ConstraintValidatorSupport<HelperAnnotation, HelperBean> {
    @Override
    public boolean isValid(final HelperBean bean, final ConstraintValidatorContext context) {
      context.disableDefaultConstraintViolation();

      // build a custom property path
      ConstraintViolationBuilder builder = context.buildConstraintViolationWithTemplate(bean.getMessage());
      NodeBuilderCustomizableContext nodeBuilder = null;
      for (String part : bean.getPath().split("\\.")) {
        if (nodeBuilder == null) {
          nodeBuilder = builder.addPropertyNode(part);
        }
        else {
          nodeBuilder = nodeBuilder.addPropertyNode(part);
        }
      }
      if (nodeBuilder != null) {
        nodeBuilder.addConstraintViolation();
      }

      return false;
    }
  }
}

We found multiple paths flowing into ConstraintViolationFactory.createViolation(1). This issue (GHSL-2020-011) focuses on the endpoints which are accessible to any authenticated user, no matter the permissions granted.

On src/main/java/org/sonatype/nexus/repository/rest/api/AbstractGroupRepositoriesApiResource.java:97 group format and members are validated and failures are reported using the insecure createViolation method:

private void validateGroupMembers(T request) {
  String groupFormat = request.getFormat();
  Set<ConstraintViolation<?>> violations = Sets.newHashSet();
  Collection<String> memberNames = request.getGroup().getMemberNames();
  for (String repositoryName : memberNames) {
    Repository repository = repositoryManager.get(repositoryName);
    if (nonNull(repository)) {
      String memberFormat = repository.getFormat().getValue();
      if (!memberFormat.equals(groupFormat)) {
        violations.add(constraintViolationFactory.createViolation("memberNames",
            "Member repository format does not match group repository format: " + repositoryName));
      }
    }
    else {
      violations.add(constraintViolationFactory.createViolation("memberNames",
          "Member repository does not exist: " + repositoryName));
    }
  }
  maybePropagate(violations, log);
}

This sink can be reached from any class extending AbstractGroupRepositoriesApiResource. At the moment of reporting, there is only one class that meets this requirement: GolangGroupRepositoriesApiResource.

These paths can be exercised by creating or updating a GoLang group repository which enforces authentication but since authorization checks are performed after bean validation, the RCE sink can be reached by any authenticated user.

Impact

This issue may lead to Remote Code execution by any low-privilege user

Remediation

Apply stripJavaEL() in HelperValidator:

ConstraintViolationBuilder builder = context.buildConstraintViolationWithTemplate(getEscapeHelper().stripJavaEl(bean.getMessage()));

Coordinated Disclosure Timeline

  • 02/03/2020: Report sent to Sonatype
  • 02/03/2020: Sonatype acknowledged report
  • 02/14/2020: Sonatype raises questions about some of the issues
  • 02/17/2020: GHSL answers Sonatype questions
  • 02/19/2020: Sonatype agrees with GHSL comments

Vendor advisories

CVE-2020-10199 Nexus Repository Manager 3 - Remote Code Execution - 2020-03-31

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 the GHSL-2020-011 in any communication regarding this issue.