Manjunath
Manjunath

Reputation: 824

The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "" after upgrade to 2.2.5

Caused by: java.lang.IllegalArgumentException: The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.
at org.apache.coyote.ajp.AbstractAjpProtocol.start(AbstractAjpProtocol.java:264)
at org.apache.catalina.connector.Connector.startInternal(Connector.java:1035) ... 22 common frames omitted

I am seeing the above errors after upgrading Spring Boot from 2.1.9 to 2.2.5. The upgrade was necessary to overcome a Ghostcat vulnerability by upgrading Tomcat version to 9.0.31, which is being bundled with the latest Spring Boot 2.2.5.

Upvotes: 62

Views: 135508

Answers (5)

Jainender Chauhan
Jainender Chauhan

Reputation: 847

Navigate to the server.xml in tomcat:

Replace AJP with:

<Connector protocol="AJP/1.3" address="::1" port="8009"
           redirectPort="8443" secretRequired="false" />

But make sure that you understand the security implications of that (see Krzysztof Skrzynecki's answer for that).

Upvotes: 71

Sysadmin
Sysadmin

Reputation: 129

Should be:

redirectPort="8443" />

secretRequired="false" />

Upvotes: 0

Vy Do
Vy Do

Reputation: 52774

Old, file conf/server.xml

<Connector protocol="AJP/1.3" address="::1" port="8089" redirectPort="8443">

New, file conf/server.xml

<Connector protocol="AJP/1.3" address="::1" port="8089" redirectPort="8443" secretRequired="false">

Upvotes: 2

Krzysztof Skrzynecki
Krzysztof Skrzynecki

Reputation: 2545

Using secretRequired="false" reintroduces Ghostcat breach what has been explained e.g. here:

This is a configuration issue with AJP protocol in Tomcat/Undertow. AJP is a highly trusted protocol and should never be exposed to untrusted clients. It is insecure (clear text transmission) and assumes that your network is safe. The preventive measures should be taken by using the configuration that will not allow AJP to be exposed.

In order of preference, one of the following mitigations should be applied:

  • ...
  • Protect the AJP connection with a secret, as well as carefully reviewing network binding and firewall configuration to ensure incoming connections are only allowed from trusted hosts.
  • ...

And here how secure configuration should look like:

@Configuration
public class TomcatConfig {


  @Bean
  public TomcatServletWebServerFactory servletContainer() {
      TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
      Connector ajpConnector = new Connector("org.apache.coyote.ajp.AjpNioProtocol");
      AjpNioProtocol protocol= (AjpNioProtocol)ajpConnector.getProtocolHandler();
      protocol.setSecret("myapjsecret");
      ajpConnector.setPort(9090);
      ajpConnector.setSecure(true);
      tomcat.addAdditionalTomcatConnectors(ajpConnector);
      return tomcat;
  }
}

Upvotes: 33

TechFree
TechFree

Reputation: 2974

Here is one solution, though probably not the best one, but my focus was not this, just to pass through the error, I was enabling AJP on Spring Boot 2.2.5.RELEASE version. Add this:

((AbstractAjpProtocol) ajpConnector.getProtocolHandler()).setSecretRequired(false);

My full class for AJP configuration:

package com.ssldemo.config;

import org.apache.catalina.connector.Connector;
import org.apache.coyote.ajp.AbstractAjpProtocol;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TomcatConfiguration {

    @Value("${tomcat.ajp.port}")
    int ajpPort;

    @Value("${tomcat.ajp.remoteauthentication}")
    String remoteAuthentication;

    @Value("${tomcat.ajp.enabled}")
    boolean tomcatAjpEnabled;

    @Bean
    public TomcatServletWebServerFactory servletContainer() {

        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        if (tomcatAjpEnabled) {
            Connector ajpConnector = new Connector("AJP/1.3");
            ajpConnector.setPort(ajpPort);
            ajpConnector.setSecure(false);
            ajpConnector.setAllowTrace(false);
            ajpConnector.setScheme("http");
            ((AbstractAjpProtocol) ajpConnector.getProtocolHandler()).setSecretRequired(false);
            tomcat.addAdditionalTomcatConnectors(ajpConnector);
        }

        return tomcat;
    }

}

application.properties

server.port=8082
tomcat.ajp.port=9090
tomcat.ajp.remoteauthentication=false
tomcat.ajp.enabled=true

Upvotes: 16

Related Questions