VYPR
High severityNVD Advisory· Published Jan 26, 2021· Updated Aug 4, 2024

CVE-2020-9492

CVE-2020-9492

Description

In Apache Hadoop 3.2.0 to 3.2.1, 3.0.0-alpha1 to 3.1.3, and 2.0.0-alpha to 2.10.0, WebHDFS client might send SPNEGO authorization header to remote URL without proper verification.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

An information disclosure vulnerability in Apache Hadoop WebHDFS that leaks SPNEGO authentication tokens to arbitrary servers via crafted URL paths.

Root

Cause

CVE-2020-9492 is a vulnerability in Apache Hadoop’s WebHDFS client that causes the process to send a SPNEGO (Kerberos) authorization header to a remote URL without properly verifying its destination. The flaw exists because the client does not validate that the target URL is a legitimate Hadoop service endpoint before attaching the SPNEGO token, which is typically used for Kerberos-based single sign-on authentication [1][3].

Exploitation

Attack Surface

An attacker who can induce the WebHDFS client—for example through a crafted request or by serving a malicious redirect—can cause the client to forward the SPNEGO token to any arbitrary server under the attacker’s control. The vulnerability requires that the client be making an HTTP request and that the attacker controls the destination URL (e.g., via a malicious redirect or manipulated path). A patch for this issue modifies the authentication filter initialization by removing the proxy-user capability that could inadvertently forward credentials, simplifying the filter to use only standard Kerberos SPNEGO authentication without proxy user functionality [3].

Impact

If successfully exploited, an attacker could intercept a valid Kerberos SPNEGO token. This token could then be replayed or used to impersonate the victim client against other Kerberized Hadoop services, leading to unauthorized access to data or actions within the Hadoop cluster. The impact is limited to the disclosure of authentication credentials; the attacker does not gain direct code execution but can escalate privileges within the Hadoop ecosystem.

Mitigation

Status

Apache Hadoop versions 3.2.0 through 3.2.1, 3.0.0-alpha1 through 3.1.3, and 2.0.0-alpha through 2.10.0 are affected. The fix is included in Hadoop 3.2.2, 3.1.4, and 2.10.1. Users should upgrade to a patched version immediately [1]. No workaround is publicly documented as a full substitute for the patch.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.apache.hadoop:hadoop-commonMaven
>= 3.2.0, < 3.2.23.2.2
org.apache.hadoop:hadoop-commonMaven
>= 3.0.0, < 3.1.43.1.4
org.apache.hadoop:hadoop-commonMaven
>= 2.0.0, < 2.10.12.10.1

Affected products

3

Patches

1
ca65409836d2

Revert "HADOOP-13119. Add ability to secure log servlet using proxy users. Contribute by Yuanbo Liu."

https://github.com/apache/hadoopOwen O'MalleyMar 1, 2018via ghsa
5 files changed · +13 686
  • hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/AuthenticationFilterInitializer.java+3 6 modified
    @@ -29,9 +29,8 @@
     import java.util.Map;
     
     /**
    - * Initializes {@link AuthenticationWithProxyUserFilter}
    - * which provides support for Kerberos HTTP SPNEGO authentication
    - * and proxy user authentication.
    + * Initializes hadoop-auth AuthenticationFilter which provides support for
    + * Kerberos HTTP SPNEGO authentication.
      * <p/>
      * It enables anonymous access, simple/speudo and Kerberos HTTP SPNEGO
      * authentication  for Hadoop JobTracker, NameNode, DataNodes and
    @@ -59,10 +58,8 @@ public class AuthenticationFilterInitializer extends FilterInitializer {
       public void initFilter(FilterContainer container, Configuration conf) {
         Map<String, String> filterConfig = getFilterConfigMap(conf, PREFIX);
     
    -    // extend AuthenticationFilter's feature to
    -    // support proxy user operation.
         container.addFilter("authentication",
    -                        AuthenticationWithProxyUserFilter.class.getName(),
    +                        AuthenticationFilter.class.getName(),
                             filterConfig);
       }
     
    
  • hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/AuthenticationWithProxyUserFilter.java+0 119 removed
    @@ -1,119 +0,0 @@
    -/**
    - * Licensed to the Apache Software Foundation (ASF) under one
    - * or more contributor license agreements.  See the NOTICE file
    - * distributed with this work for additional information
    - * regarding copyright ownership.  The ASF licenses this file
    - * to you under the Apache License, Version 2.0 (the
    - * "License"); you may not use this file except in compliance
    - * with the License.  You may obtain a copy of the License at
    - * <p>
    - * http://www.apache.org/licenses/LICENSE-2.0
    - * <p>
    - * Unless required by applicable law or agreed to in writing, software
    - * distributed under the License is distributed on an "AS IS" BASIS,
    - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    - * See the License for the specific language governing permissions and
    - * limitations under the License.
    - */
    -package org.apache.hadoop.security;
    -
    -import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
    -import org.apache.hadoop.security.authorize.AuthorizationException;
    -import org.apache.hadoop.security.authorize.ProxyUsers;
    -import org.apache.hadoop.util.HttpExceptionUtils;
    -import org.apache.http.NameValuePair;
    -import org.apache.http.client.utils.URLEncodedUtils;
    -
    -import javax.servlet.FilterChain;
    -import javax.servlet.ServletException;
    -import javax.servlet.http.HttpServletRequest;
    -import javax.servlet.http.HttpServletRequestWrapper;
    -import javax.servlet.http.HttpServletResponse;
    -import java.io.IOException;
    -import java.nio.charset.Charset;
    -import java.util.List;
    -
    -/**
    - * Extend the function of {@link AuthenticationFilter} to
    - * support authorizing proxy user. If the query string
    - * contains doAs parameter, then check the proxy user,
    - * otherwise do the next filter.
    - */
    -public class AuthenticationWithProxyUserFilter extends AuthenticationFilter {
    -
    -  /**
    -   * Constant used in URL's query string to perform a proxy user request, the
    -   * value of the <code>DO_AS</code> parameter is the user the request will be
    -   * done on behalf of.
    -   */
    -  private static final String DO_AS = "doAs";
    -
    -  private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
    -
    -
    -  /**
    -   * This method provide the ability to do pre/post tasks
    -   * in filter chain. Override this method to authorize
    -   * proxy user between AuthenticationFilter and next filter.
    -   * @param filterChain the filter chain object.
    -   * @param request the request object.
    -   * @param response the response object.
    -   *
    -   * @throws IOException
    -   * @throws ServletException
    -   */
    -  @Override
    -  protected void doFilter(FilterChain filterChain, HttpServletRequest request,
    -      HttpServletResponse response) throws IOException, ServletException {
    -
    -    // authorize proxy user before calling next filter.
    -    String proxyUser = getDoAs(request);
    -    if (proxyUser != null) {
    -      UserGroupInformation realUser =
    -          UserGroupInformation.createRemoteUser(request.getRemoteUser());
    -      UserGroupInformation proxyUserInfo =
    -          UserGroupInformation.createProxyUser(proxyUser, realUser);
    -
    -      try {
    -        ProxyUsers.authorize(proxyUserInfo, request.getRemoteAddr());
    -      } catch (AuthorizationException ex) {
    -        HttpExceptionUtils.createServletExceptionResponse(response,
    -            HttpServletResponse.SC_FORBIDDEN, ex);
    -        // stop filter chain if there is an Authorization Exception.
    -        return;
    -      }
    -
    -      final UserGroupInformation finalProxyUser = proxyUserInfo;
    -      // Change the remote user after proxy user is authorized.
    -      request = new HttpServletRequestWrapper(request) {
    -        @Override
    -        public String getRemoteUser() {
    -          return finalProxyUser.getUserName();
    -        }
    -      };
    -
    -    }
    -    filterChain.doFilter(request, response);
    -  }
    -
    -  /**
    -   * Get proxy user from query string.
    -   * @param request the request object
    -   * @return proxy user
    -   */
    -  public static String getDoAs(HttpServletRequest request) {
    -    String queryString = request.getQueryString();
    -    if (queryString == null) {
    -      return null;
    -    }
    -    List<NameValuePair> list = URLEncodedUtils.parse(queryString, UTF8_CHARSET);
    -    if (list != null) {
    -      for (NameValuePair nv : list) {
    -        if (DO_AS.equalsIgnoreCase(nv.getName())) {
    -          return nv.getValue();
    -        }
    -      }
    -    }
    -    return null;
    -  }
    -}
    
  • hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServerWithSpengo.java+0 480 removed
    @@ -1,480 +0,0 @@
    -/**
    - * Licensed to the Apache Software Foundation (ASF) under one
    - * or more contributor license agreements.  See the NOTICE file
    - * distributed with this work for additional information
    - * regarding copyright ownership.  The ASF licenses this file
    - * to you under the Apache License, Version 2.0 (the
    - * "License"); you may not use this file except in compliance
    - * with the License.  You may obtain a copy of the License at
    - * <p>
    - * http://www.apache.org/licenses/LICENSE-2.0
    - * <p>
    - * Unless required by applicable law or agreed to in writing, software
    - * distributed under the License is distributed on an "AS IS" BASIS,
    - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    - * See the License for the specific language governing permissions and
    - * limitations under the License.
    - */
    -package org.apache.hadoop.http;
    -
    -import org.apache.hadoop.conf.Configuration;
    -import org.apache.hadoop.fs.CommonConfigurationKeys;
    -import org.apache.hadoop.minikdc.MiniKdc;
    -import org.apache.hadoop.net.NetUtils;
    -import org.apache.hadoop.security.AuthenticationFilterInitializer;
    -import org.apache.hadoop.security.SecurityUtil;
    -import org.apache.hadoop.security.UserGroupInformation;
    -import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
    -import org.apache.hadoop.security.authentication.KerberosTestUtils;
    -import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
    -import org.apache.hadoop.security.authentication.client.AuthenticationException;
    -import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
    -import org.apache.hadoop.security.authentication.server.AuthenticationToken;
    -import org.apache.hadoop.security.authentication.util.Signer;
    -import org.apache.hadoop.security.authentication.util.SignerSecretProvider;
    -import org.apache.hadoop.security.authentication.util.StringSignerSecretProviderCreator;
    -import org.apache.hadoop.security.authorize.AccessControlList;
    -import org.apache.hadoop.security.authorize.ProxyUsers;
    -import org.ietf.jgss.GSSException;
    -import org.junit.AfterClass;
    -import org.junit.BeforeClass;
    -import org.junit.Test;
    -import org.junit.Assert;
    -import org.slf4j.Logger;
    -import org.slf4j.LoggerFactory;
    -
    -import java.io.File;
    -import java.io.FileWriter;
    -import java.io.Writer;
    -import java.net.HttpURLConnection;
    -import java.net.URI;
    -import java.net.URL;
    -import java.security.AccessController;
    -import java.security.PrivilegedExceptionAction;
    -import java.util.HashSet;
    -import java.util.Properties;
    -import java.util.Set;
    -import javax.security.auth.Subject;
    -import javax.servlet.ServletContext;
    -
    -import static org.junit.Assert.assertTrue;
    -
    -/**
    - * This class is tested for http server with SPENGO authentication.
    - */
    -public class TestHttpServerWithSpengo {
    -
    -  static final Logger LOG =
    -      LoggerFactory.getLogger(TestHttpServerWithSpengo.class);
    -
    -  private static final String SECRET_STR = "secret";
    -  private static final String HTTP_USER = "HTTP";
    -  private static final String PREFIX = "hadoop.http.authentication.";
    -  private static final long TIMEOUT = 20000;
    -
    -  private static File httpSpnegoKeytabFile = new File(
    -      KerberosTestUtils.getKeytabFile());
    -  private static String httpSpnegoPrincipal =
    -      KerberosTestUtils.getServerPrincipal();
    -  private static String realm = KerberosTestUtils.getRealm();
    -
    -  private static File testRootDir = new File("target",
    -      TestHttpServerWithSpengo.class.getName() + "-root");
    -  private static MiniKdc testMiniKDC;
    -  private static File secretFile = new File(testRootDir, SECRET_STR);
    -
    -  private static UserGroupInformation authUgi;
    -
    -  @BeforeClass
    -  public static void setUp() throws Exception {
    -    try {
    -      testMiniKDC = new MiniKdc(MiniKdc.createConf(), testRootDir);
    -      testMiniKDC.start();
    -      testMiniKDC.createPrincipal(
    -          httpSpnegoKeytabFile, HTTP_USER + "/localhost", "keytab-user");
    -    } catch (Exception e) {
    -      assertTrue("Couldn't setup MiniKDC", false);
    -    }
    -
    -    System.setProperty("sun.security.krb5.debug", "true");
    -    Configuration conf = new Configuration();
    -    SecurityUtil.setAuthenticationMethod(AuthenticationMethod.KERBEROS, conf);
    -    UserGroupInformation.setConfiguration(conf);
    -    authUgi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(
    -        "keytab-user", httpSpnegoKeytabFile.toString());
    -    Writer w = new FileWriter(secretFile);
    -    w.write("secret");
    -    w.close();
    -  }
    -
    -  @AfterClass
    -  public static void tearDown() {
    -    if (testMiniKDC != null) {
    -      testMiniKDC.stop();
    -    }
    -  }
    -
    -  /**
    -   * groupA
    -   *  - userA
    -   * groupB
    -   *  - userA, userB
    -   * groupC
    -   *  - userC
    -   * SPNEGO filter has been enabled.
    -   * userA has the privilege to impersonate users in groupB.
    -   * userA has admin access to all default servlets, but userB
    -   * and userC don't have. So "/logs" can only be accessed by userA.
    -   * @throws Exception
    -   */
    -  @Test
    -  public void testAuthenticationWithProxyUser() throws Exception {
    -
    -    Configuration spengoConf = getSpengoConf(new Configuration());
    -
    -    //setup logs dir
    -    System.setProperty("hadoop.log.dir", testRootDir.getAbsolutePath());
    -
    -    // Setup user group
    -    UserGroupInformation.createUserForTesting("userA",
    -        new String[]{"groupA", "groupB"});
    -    UserGroupInformation.createUserForTesting("userB",
    -        new String[]{"groupB"});
    -    UserGroupInformation.createUserForTesting("userC",
    -        new String[]{"groupC"});
    -
    -    // Make userA impersonate users in groupB
    -    spengoConf.set("hadoop.proxyuser.userA.hosts", "*");
    -    spengoConf.set("hadoop.proxyuser.userA.groups", "groupB");
    -    ProxyUsers.refreshSuperUserGroupsConfiguration(spengoConf);
    -
    -    HttpServer2 httpServer = null;
    -    try {
    -      // Create http server to test.
    -      httpServer = getCommonBuilder()
    -          .setConf(spengoConf)
    -          .setACL(new AccessControlList("userA groupA"))
    -          .build();
    -      httpServer.start();
    -
    -      // Get signer to encrypt token
    -      Signer signer = getSignerToEncrypt();
    -
    -      // setup auth token for userA
    -      AuthenticatedURL.Token token = getEncryptedAuthToken(signer, "userA");
    -
    -      String serverURL = "http://" +
    -          NetUtils.getHostPortString(httpServer.getConnectorAddress(0)) + "/";
    -
    -      // The default authenticator is kerberos.
    -      AuthenticatedURL authUrl = new AuthenticatedURL();
    -
    -      // userA impersonates userB, it's allowed.
    -      for (String servlet :
    -          new String[]{"stacks", "jmx", "conf"}) {
    -        HttpURLConnection conn = authUrl
    -            .openConnection(new URL(serverURL + servlet + "?doAs=userB"),
    -                token);
    -        Assert.assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
    -      }
    -
    -      // userA cannot impersonate userC, it fails.
    -      for (String servlet :
    -          new String[]{"stacks", "jmx", "conf"}){
    -        HttpURLConnection conn = authUrl
    -            .openConnection(new URL(serverURL + servlet + "?doAs=userC"),
    -                token);
    -        Assert.assertEquals(HttpURLConnection.HTTP_FORBIDDEN,
    -            conn.getResponseCode());
    -      }
    -
    -      // "/logs" and "/logLevel" require admin authorization,
    -      // only userA has the access.
    -      for (String servlet :
    -          new String[]{"logLevel", "logs"}) {
    -        HttpURLConnection conn = authUrl
    -            .openConnection(new URL(serverURL + servlet), token);
    -        Assert.assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
    -      }
    -
    -      // Setup token for userB
    -      token = getEncryptedAuthToken(signer, "userB");
    -
    -      // userB cannot access these servlets.
    -      for (String servlet :
    -          new String[]{"logLevel", "logs"}) {
    -        HttpURLConnection conn = authUrl
    -            .openConnection(new URL(serverURL + servlet), token);
    -        Assert.assertEquals(HttpURLConnection.HTTP_FORBIDDEN,
    -            conn.getResponseCode());
    -      }
    -
    -    } finally {
    -      if (httpServer != null) {
    -        httpServer.stop();
    -      }
    -    }
    -  }
    -
    -  @Test
    -  public void testSessionCookie() throws Exception {
    -    Configuration conf = new Configuration();
    -    conf.set(HttpServer2.FILTER_INITIALIZER_PROPERTY,
    -        AuthenticationFilterInitializer.class.getName());
    -    conf.set(PREFIX + "type", "kerberos");
    -    conf.setBoolean(PREFIX + "simple.anonymous.allowed", false);
    -    conf.set(PREFIX + "signer.secret.provider",
    -        TestSignerSecretProvider.class.getName());
    -
    -    conf.set(PREFIX + "kerberos.keytab",
    -        httpSpnegoKeytabFile.getAbsolutePath());
    -    conf.set(PREFIX + "kerberos.principal", httpSpnegoPrincipal);
    -    conf.set(PREFIX + "cookie.domain", realm);
    -    conf.setBoolean(CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION,
    -        true);
    -
    -    //setup logs dir
    -    System.setProperty("hadoop.log.dir", testRootDir.getAbsolutePath());
    -
    -    HttpServer2 httpServer = null;
    -    // Create http server to test.
    -    httpServer = getCommonBuilder()
    -        .setConf(conf)
    -        .build();
    -    httpServer.start();
    -
    -    // Get signer to encrypt token
    -    final Signer signer = new Signer(new TestSignerSecretProvider());
    -    final AuthenticatedURL authUrl = new AuthenticatedURL();
    -
    -    final URL url = new URL("http://" + NetUtils.getHostPortString(
    -        httpServer.getConnectorAddress(0)) + "/conf");
    -
    -    // this illustrates an inconsistency with AuthenticatedURL.  the
    -    // authenticator is only called when the token is not set.  if the
    -    // authenticator fails then it must throw an AuthenticationException to
    -    // the caller, yet the caller may see 401 for subsequent requests
    -    // that require re-authentication like token expiration.
    -    final UserGroupInformation simpleUgi =
    -        UserGroupInformation.createRemoteUser("simple-user");
    -
    -    authUgi.doAs(new PrivilegedExceptionAction<Void>() {
    -      @Override
    -      public Void run() throws Exception {
    -        TestSignerSecretProvider.rollSecret();
    -        HttpURLConnection conn = null;
    -        AuthenticatedURL.Token token = new AuthenticatedURL.Token();
    -
    -        // initial request should trigger authentication and set the token.
    -        conn = authUrl.openConnection(url, token);
    -        Assert.assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
    -        Assert.assertTrue(token.isSet());
    -        String cookie = token.toString();
    -
    -        // token should not change.
    -        conn = authUrl.openConnection(url, token);
    -        Assert.assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
    -        Assert.assertTrue(token.isSet());
    -        Assert.assertEquals(cookie, token.toString());
    -
    -        // roll secret to invalidate token.
    -        TestSignerSecretProvider.rollSecret();
    -        conn = authUrl.openConnection(url, token);
    -        // this may or may not happen.  under normal circumstances the
    -        // jdk will silently renegotiate and the client never sees a 401.
    -        // however in some cases the jdk will give up doing spnego.  since
    -        // the token is already set, the authenticator isn't invoked (which
    -        // would do the spnego if the jdk doesn't), which causes the client
    -        // to see a 401.
    -        if (conn.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) {
    -          // if this happens, the token should be cleared which means the
    -          // next request should succeed and receive a new token.
    -          Assert.assertFalse(token.isSet());
    -          conn = authUrl.openConnection(url, token);
    -        }
    -
    -        // token should change.
    -        Assert.assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
    -        Assert.assertTrue(token.isSet());
    -        Assert.assertNotEquals(cookie, token.toString());
    -        cookie = token.toString();
    -
    -        // token should not change.
    -        for (int i=0; i < 3; i++) {
    -          conn = authUrl.openConnection(url, token);
    -          Assert.assertEquals("attempt"+i,
    -              HttpURLConnection.HTTP_OK, conn.getResponseCode());
    -          Assert.assertTrue(token.isSet());
    -          Assert.assertEquals(cookie, token.toString());
    -        }
    -
    -        // blow out the kerberos creds test only auth token is used.
    -        Subject s = Subject.getSubject(AccessController.getContext());
    -        Set<Object> oldCreds = new HashSet<>(s.getPrivateCredentials());
    -        s.getPrivateCredentials().clear();
    -
    -        // token should not change.
    -        for (int i=0; i < 3; i++) {
    -          try {
    -            conn = authUrl.openConnection(url, token);
    -            Assert.assertEquals("attempt"+i,
    -                HttpURLConnection.HTTP_OK, conn.getResponseCode());
    -          } catch (AuthenticationException ae) {
    -            Assert.fail("attempt"+i+" "+ae);
    -          }
    -          Assert.assertTrue(token.isSet());
    -          Assert.assertEquals(cookie, token.toString());
    -        }
    -
    -        // invalidate token.  connections should fail now and token should be
    -        // unset.
    -        TestSignerSecretProvider.rollSecret();
    -        conn = authUrl.openConnection(url, token);
    -        Assert.assertEquals(
    -            HttpURLConnection.HTTP_UNAUTHORIZED, conn.getResponseCode());
    -        Assert.assertFalse(token.isSet());
    -        Assert.assertEquals("", token.toString());
    -
    -        // restore the kerberos creds, should work again.
    -        s.getPrivateCredentials().addAll(oldCreds);
    -        conn = authUrl.openConnection(url, token);
    -        Assert.assertEquals(
    -            HttpURLConnection.HTTP_OK, conn.getResponseCode());
    -        Assert.assertTrue(token.isSet());
    -        cookie = token.toString();
    -
    -        // token should not change.
    -        for (int i=0; i < 3; i++) {
    -          conn = authUrl.openConnection(url, token);
    -          Assert.assertEquals("attempt"+i,
    -              HttpURLConnection.HTTP_OK, conn.getResponseCode());
    -          Assert.assertTrue(token.isSet());
    -          Assert.assertEquals(cookie, token.toString());
    -        }
    -        return null;
    -      }
    -    });
    -
    -    simpleUgi.doAs(new PrivilegedExceptionAction<Void>() {
    -      @Override
    -      public Void run() throws Exception {
    -        TestSignerSecretProvider.rollSecret();
    -        AuthenticatedURL authUrl = new AuthenticatedURL();
    -        AuthenticatedURL.Token token = new AuthenticatedURL.Token();
    -        HttpURLConnection conn = null;
    -
    -        // initial connect with unset token will trigger authenticator which
    -        // should fail since we have no creds and leave token unset.
    -        try {
    -          authUrl.openConnection(url, token);
    -          Assert.fail("should fail with no credentials");
    -        } catch (AuthenticationException ae) {
    -          Assert.assertNotNull(ae.getCause());
    -          Assert.assertEquals(GSSException.class, ae.getCause().getClass());
    -          GSSException gsse = (GSSException)ae.getCause();
    -          Assert.assertEquals(GSSException.NO_CRED, gsse.getMajor());
    -        } catch (Throwable t) {
    -          Assert.fail("Unexpected exception" + t);
    -        }
    -        Assert.assertFalse(token.isSet());
    -
    -        // create a valid token and save its value.
    -        token = getEncryptedAuthToken(signer, "valid");
    -        String cookie = token.toString();
    -
    -        // server should accept token.  after the request the token should
    -        // be set to the same value (ie. server didn't reissue cookie)
    -        conn = authUrl.openConnection(url, token);
    -        Assert.assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
    -        Assert.assertTrue(token.isSet());
    -        Assert.assertEquals(cookie, token.toString());
    -
    -        conn = authUrl.openConnection(url, token);
    -        Assert.assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
    -        Assert.assertTrue(token.isSet());
    -        Assert.assertEquals(cookie, token.toString());
    -
    -        // change the secret to effectively invalidate the cookie.  see above
    -        // regarding inconsistency.  the authenticator has no way to know the
    -        // token is bad, so the client will encounter a 401 instead of
    -        // AuthenticationException.
    -        TestSignerSecretProvider.rollSecret();
    -        conn = authUrl.openConnection(url, token);
    -        Assert.assertEquals(
    -            HttpURLConnection.HTTP_UNAUTHORIZED, conn.getResponseCode());
    -        Assert.assertFalse(token.isSet());
    -        Assert.assertEquals("", token.toString());
    -        return null;
    -      }
    -    });
    -  }
    -
    -  public static class TestSignerSecretProvider extends SignerSecretProvider {
    -    static int n = 0;
    -    static byte[] secret;
    -
    -    static void rollSecret() {
    -      secret = ("secret[" + (n++) + "]").getBytes();
    -    }
    -
    -    public TestSignerSecretProvider() {
    -    }
    -
    -    @Override
    -    public void init(Properties config, ServletContext servletContext,
    -            long tokenValidity) throws Exception {
    -      rollSecret();
    -    }
    -
    -    @Override
    -    public byte[] getCurrentSecret() {
    -      return secret;
    -    }
    -
    -    @Override
    -    public byte[][] getAllSecrets() {
    -      return new byte[][]{secret};
    -    }
    -  }
    -
    -  private AuthenticatedURL.Token getEncryptedAuthToken(Signer signer,
    -      String user) throws Exception {
    -    AuthenticationToken token =
    -        new AuthenticationToken(user, user, "kerberos");
    -    token.setExpires(System.currentTimeMillis() + TIMEOUT);
    -    return new AuthenticatedURL.Token(signer.sign(token.toString()));
    -  }
    -
    -  private Signer getSignerToEncrypt() throws Exception {
    -    SignerSecretProvider secretProvider =
    -        StringSignerSecretProviderCreator.newStringSignerSecretProvider();
    -    Properties secretProviderProps = new Properties();
    -    secretProviderProps.setProperty(
    -        AuthenticationFilter.SIGNATURE_SECRET, SECRET_STR);
    -    secretProvider.init(secretProviderProps, null, TIMEOUT);
    -    return new Signer(secretProvider);
    -  }
    -
    -  private Configuration getSpengoConf(Configuration conf) {
    -    conf = new Configuration();
    -    conf.set(HttpServer2.FILTER_INITIALIZER_PROPERTY,
    -        AuthenticationFilterInitializer.class.getName());
    -    conf.set(PREFIX + "type", "kerberos");
    -    conf.setBoolean(PREFIX + "simple.anonymous.allowed", false);
    -    conf.set(PREFIX + "signature.secret.file",
    -        secretFile.getAbsolutePath());
    -    conf.set(PREFIX + "kerberos.keytab",
    -        httpSpnegoKeytabFile.getAbsolutePath());
    -    conf.set(PREFIX + "kerberos.principal", httpSpnegoPrincipal);
    -    conf.set(PREFIX + "cookie.domain", realm);
    -    conf.setBoolean(CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION,
    -        true);
    -    return conf;
    -  }
    -
    -  private HttpServer2.Builder getCommonBuilder() throws Exception {
    -    return new HttpServer2.Builder().setName("test")
    -        .addEndpoint(new URI("http://localhost:0"))
    -        .setFindPort(true);
    -  }
    -}
    
  • hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestAuthenticationFilter.java+10 3 modified
    @@ -19,12 +19,16 @@
     
     import junit.framework.TestCase;
     import org.apache.hadoop.http.HttpServer2;
    +import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
     import org.apache.hadoop.conf.Configuration;
     import org.apache.hadoop.http.FilterContainer;
     import org.mockito.Mockito;
     import org.mockito.invocation.InvocationOnMock;
     import org.mockito.stubbing.Answer;
     
    +import java.io.File;
    +import java.io.FileWriter;
    +import java.io.Writer;
     import java.util.Map;
     
     public class TestAuthenticationFilter extends TestCase {
    @@ -38,14 +42,16 @@ public void testConfiguration() throws Exception {
         
         FilterContainer container = Mockito.mock(FilterContainer.class);
         Mockito.doAnswer(
    -        new Answer() {
    +      new Answer() {
             @Override
             public Object answer(InvocationOnMock invocationOnMock)
               throws Throwable {
               Object[] args = invocationOnMock.getArguments();
     
               assertEquals("authentication", args[0]);
     
    +          assertEquals(AuthenticationFilter.class.getName(), args[1]);
    +
               Map<String, String> conf = (Map<String, String>) args[2];
               assertEquals("/", conf.get("cookie.path"));
     
    @@ -60,8 +66,9 @@ public Object answer(InvocationOnMock invocationOnMock)
               assertEquals("bar", conf.get("foo"));
     
               return null;
    -        }}
    -        ).when(container).addFilter(Mockito.<String>anyObject(),
    +        }
    +      }
    +    ).when(container).addFilter(Mockito.<String>anyObject(),
                                     Mockito.<String>anyObject(),
                                     Mockito.<Map<String, String>>anyObject());
     
    
  • hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestAuthenticationWithProxyUserFilter.java+0 78 removed
    @@ -1,78 +0,0 @@
    -/**
    - * Licensed to the Apache Software Foundation (ASF) under one or more
    - * contributor license agreements. See the NOTICE file distributed with this
    - * work for additional information regarding copyright ownership. The ASF
    - * licenses this file to you under the Apache License, Version 2.0 (the
    - * "License"); you may not use this file except in compliance with the License.
    - * You may obtain a copy of the License at
    - *
    - * http://www.apache.org/licenses/LICENSE-2.0
    - *
    - * Unless required by applicable law or agreed to in writing, software
    - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    - * License for the specific language governing permissions and limitations under
    - * the License.
    - */
    -package org.apache.hadoop.security;
    -
    -
    -import junit.framework.TestCase;
    -import org.apache.hadoop.http.HttpServer2;
    -import org.apache.hadoop.conf.Configuration;
    -import org.apache.hadoop.http.FilterContainer;
    -import org.mockito.Mockito;
    -import org.mockito.invocation.InvocationOnMock;
    -import org.mockito.stubbing.Answer;
    -import java.util.Map;
    -
    -/**
    - * This class is tested for {@link AuthenticationWithProxyUserFilter}
    - * to verify configurations of this filter.
    - */
    -public class TestAuthenticationWithProxyUserFilter extends TestCase {
    -
    -  @SuppressWarnings("unchecked")
    -  public void testConfiguration() throws Exception {
    -    Configuration conf = new Configuration();
    -    conf.set("hadoop.http.authentication.foo", "bar");
    -
    -    conf.set(HttpServer2.BIND_ADDRESS, "barhost");
    -
    -    FilterContainer container = Mockito.mock(FilterContainer.class);
    -    Mockito.doAnswer(
    -      new Answer() {
    -        @Override
    -        public Object answer(InvocationOnMock invocationOnMock)
    -          throws Throwable {
    -          Object[] args = invocationOnMock.getArguments();
    -
    -          assertEquals("authentication", args[0]);
    -
    -          assertEquals(
    -              AuthenticationWithProxyUserFilter.class.getName(), args[1]);
    -
    -          Map<String, String> conf = (Map<String, String>) args[2];
    -          assertEquals("/", conf.get("cookie.path"));
    -
    -          assertEquals("simple", conf.get("type"));
    -          assertEquals("36000", conf.get("token.validity"));
    -          assertNull(conf.get("cookie.domain"));
    -          assertEquals("true", conf.get("simple.anonymous.allowed"));
    -          assertEquals("HTTP/barhost@LOCALHOST",
    -                       conf.get("kerberos.principal"));
    -          assertEquals(System.getProperty("user.home") +
    -                       "/hadoop.keytab", conf.get("kerberos.keytab"));
    -          assertEquals("bar", conf.get("foo"));
    -
    -          return null;
    -        }
    -      }
    -    ).when(container).addFilter(Mockito.<String>anyObject(),
    -                                Mockito.<String>anyObject(),
    -                                Mockito.<Map<String, String>>anyObject());
    -
    -    new AuthenticationFilterInitializer().initFilter(container, conf);
    -  }
    -
    -}
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

33

News mentions

0

No linked articles in our index yet.