ZoomEye indexes 2,107,044 services on port 8009, the default Apache Tomcat AJP connector port. A service fingerprint for ajp13 returns 1,240,557, and the combination port="8009" && service="http" returns 620,164. A TLS handshake on the same port appears 64,404 times.
Those counts describe a port that most asset inventories do not track, because it never appears in a browser-facing scan.

What AJP is and why it exists

AJP is a binary protocol for a front-end web server to talk to Tomcat. The usual deployment places Apache httpd or IIS in front of Tomcat, terminates TLS at the front end, and forwards requests over AJP so the front end can pass a request without re-encoding it as HTTP. The AJP connector documentation is explicit about the design: the protocol supports attributes such as the remote address, the authenticated user, and the SSL certificate subject, and it can convey those to the servlet container.
That attribute-passing is the feature that becomes the vulnerability class. If a client can reach the AJP port directly, it can craft those attributes itself. CVE-2020-1938, published in 2020 and widely known as Ghostcat, is the canonical example: a request to the AJP connector could set attributes that made Tomcat treat the caller as having already authenticated, and, in the default configuration, could read files from the web application root.
The Ghostcat details matter less than the structural point they illustrate. The AJP protocol assumes the caller is a trusted reverse proxy, and nothing in the protocol verifies that assumption.

Reading the counts

2,107,044 is reachability on 8009. That is a port count, and it includes every process that happens to listen there, including ones that are not Tomcat.
1,240,557 is a service banner recognised as ajp13. This is the count that most nearly describes a reachable AJP connector, and it is still a recognition result rather than a configuration assessment.
620,164 answering HTTP on 8009 is the most informative number in the set. It means that roughly a third of the hosts on that port answered an HTTP-style request, which is not what a correctly fronted AJP connector does. A common cause is a second service bound beside the connector, or a management agent that took the port after a reconfiguration.
64,404 with a TLS handshake on 8009 is small, and the reason is structural. AJP over TLS is rare, because the normal design terminates TLS at the front end and leaves the connector in plaintext on a private network.

Where the exposure comes from

Docker images and application servers frequently publish the connector as part of the default port set. A Dockerfile that runs Tomcat, a Helm chart that exposes every container port through a LoadBalancer, and an application server profile that enables AJP by default all produce a listener that the operator never chose. The Tomcat security guidance is direct about the fix: disable the AJP connector if it is not in use, and bind it to loopback if it is.
A second source is legacy consolidation. Patching a front-end httpd and leaving the Tomcat connector reachable from the same subnet as the front end is a common landing zone design, because it keeps the network diagram simple. The design holds only while the subnet boundary is enforced.

What to verify

The review has four steps that map onto the counts above:

port="8009"
service="ajp13"
port="8009" && service="http"
port="8009" && service="ssl"

Run each query separately, record the timestamp and sub_type=all, then match the results against the Tomcat inventory. For every connector that is enabled, confirm the address attribute restricts the listener to the front-end address, confirm that requiredSecret is set so the connector rejects requests without the shared secret, and confirm the front end sends that secret. In Tomcat 9 and 10 both attributes are documented in the AJP connector reference.
Then check the orchestration layer. A container that declares
EXPOSE 8009 is a container whose port may be published, and the difference between a declared and a published port is a line in a manifest that nobody reviews.
The counts came from four ZoomEye queries executed on 2026-10-25 with
sub_type=all. They describe what the index observed at that moment, not what any individual connector allows. A reachable AJP port is a precondition for the Ghostcat class of attack, not proof that the specific instance is unpatched or exploitable.

References

  • Apache Tomcat 10 Configuration Reference, "The AJP Connector": https://tomcat.apache.org/tomcat-10.1-doc/config/ajp.html

  • Apache Tomcat 9, "Security Considerations": https://tomcat.apache.org/tomcat-9.0-doc/security-howto.html

  • NVD, CVE-2020-1938: https://nvd.nist.gov/vuln/detail/CVE-2020-1938

  • ZoomEye, queries executed 2026-10-25 with sub_type=all: https://www.zoomeye.ai/