This is not a broken front door so much as a hidden service hatch only a few buildings still use
The underlying issue is CVE-2022-26377 in mod_proxy_ajp, Apache HTTP Server's AJP proxy module. Upstream says it affects Apache HTTP Server 2.4.0 through 2.4.53, fixed in 2.4.54. The important catch is that a host is only meaningfully exposed if it is not just running an old Apache, but is also loading mod_proxy_ajp and forwarding requests to an AJP backend such as Tomcat.
That is why the raw network CVSS story overstates enterprise risk. In a vacuum, unauthenticated request smuggling against a public reverse proxy sounds like a broad internet bug; in reality this is a configuration-gated, legacy-connector flaw with a much smaller exposed population than generic Apache version checks suggest. The vendor's 'moderate/medium' framing is closer to reality than the scanner's generic high label, and for most fleets this should be downgraded to LOW unless you can prove active AJP reverse-proxy use on internet-facing apps.
4 steps from start to impact.
Find an externally reachable Apache front end
193422. Weaponization here is usually just recon plus a custom request-smuggling client or Burp's HTTP Request Smuggler-style testing workflow. This step is easy, but it does not prove exploitability.- Apache HTTP Server is reachable from the attacker
- The instance is running a version in the affected range or appears to be
- Banner/package version alone does not show whether
mod_proxy_ajpis loaded - Distro backports can make an old-looking package non-vulnerable
- Many Apache servers are not reverse proxies at all
Confirm mod_proxy_ajp is actually in the request path
ajp:// backend route, the bug is inert in practice.mod_proxy_ajpis loaded- Apache is configured with
ProxyPass, balancer members, or equivalent routes to an AJP backend - The vulnerable frontend path is attacker-reachable
- AJP is much less common than HTTP/HTTPS proxying in modern fleets
- Many organizations reduced AJP exposure after Tomcat 'Ghostcat'-era scrutiny
- This prerequisite usually cannot be verified from the internet without probing or internal config access
Desync Apache and the AJP backend
- A compatible request path exists through the vulnerable AJP proxy flow
- Frontend and backend parsing differences are reachable with attacker-controlled input
- Request smuggling often needs path-specific tuning and careful parser behavior matching
- Intermediate CDN/WAF/proxy layers may normalize or reject malformed traffic before it reaches Apache
- Operationally, reliable exploitation is noisier and less turnkey than classic one-shot RCE
Abuse backend trust assumptions
- The backend application exposes sensitive paths or trust decisions behind the AJP proxy
- The attacker can turn smuggled traffic into a meaningful app-level action
- Impact depends on what the backend actually exposes and trusts
- Many deployments will see access-control bypass or data leakage, not code execution
- Blast radius is typically limited to the proxied application tier, not the whole server
The supporting signals.
| In-the-wild status | No reviewed source showed CISA KEV inclusion or vendor-confirmed broad active exploitation. Public exploitation discussion is mainly research-driven, not mass abuse. |
|---|---|
| PoC availability | Yes. watchTowr published technical research and linked a GitHub PoC/detection-artifact generator: watchtowrlabs/ibm-qradar-ajp_smuggling_CVE-2022-26377_poc. |
| EPSS | 0.33465 (96.7th percentile) as surfaced by Docker Scout from EPSS data. That is a useful threat signal, but it still does not remove the very strong mod_proxy_ajp configuration gate. |
| KEV status | Not listed in the CISA Known Exploited Vulnerabilities catalog page reviewed. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N (7.5 HIGH in NVD). Read it as: remotely reachable, no auth, but the modeled impact is integrity on the proxied request flow, not generic RCE. |
| Affected versions | Upstream Apache says 2.4.0-2.4.53 are affected. Practical exposure requires mod_proxy_ajp enabled and actually forwarding to an AJP backend. |
| Fixed versions | Upstream fixed in 2.4.54. Examples of distro backports include Ubuntu 22.04: 2.4.52-1ubuntu4.1, Ubuntu 20.04: 2.4.41-4ubuntu3.12, and Debian 10: 2.4.38-3+deb10u8. |
| Scanner/exposure reality | Internet-wide banner data for 'Apache 2.4.x' is not decision-useful here. Shodan/Censys-style census cannot reliably tell you whether the hidden prerequisites exist: loaded mod_proxy_ajp, live ajp:// routes, and a backend that trusts the proxy boundary. |
| Disclosure timeline | Apache disclosed the issue on 2022-06-08 and shipped the 2.4.54 update the same day; NVD published on 2022-06-09. |
| Reporter / weaponization notes | Upstream credits Ricter Z @ 360 Noah Lab. Later public weaponization and impact demonstration came from watchTowr, notably against IBM QRadar. |
noisgate verdict.
The decisive factor is the hidden configuration prerequisite: this is only exploitable on Apache servers that are actively using mod_proxy_ajp to forward traffic to an AJP backend. That collapses the reachable population far below the universe implied by a plain Apache version check, even though the resulting abuse can be unauthenticated and real on the subset that uses AJP.
Why this verdict
- Strong config gate: the NVD 7.5 baseline assumes a network bug, but real exploitation requires
mod_proxy_ajpplus live AJP proxy routes. - Population collapses fast: many Apache fleets are serving static content or proxying HTTP/HTTPS, not AJP; after that first prerequisite, exposed enterprises drop sharply.
- No broad exploitation pressure: no KEV listing and no reviewed evidence of commodity mass exploitation; public activity is mainly research and targeted demonstration.
- Impact is meaningful but narrower than RCE: the abuse is backend request smuggling, access-control bypass, queue poisoning, or data leakage through the proxied app path, not a generic shell-on-webserver outcome.
- Scanner inflation matters: Tenable plugin
193422keys off version and will light up hosts that are not using AJP at all, which is the single biggest reason to downgrade this in fleet operations.
Why not higher?
It is not higher because the attack chain has a major real-world choke point before exploitation even begins: the server must be a vulnerable AJP reverse proxy, not just an old Apache. That prerequisite usually implies a niche legacy deployment pattern and sharply narrows both exposed population and expected attacker ROI. There is also no strong public signal of widespread in-the-wild exploitation pressure.
Why not lower?
It is not lower because when the prerequisite exists, the bug is still unauthenticated and remote. Request smuggling across a proxy boundary can invalidate frontend security assumptions, reach backend-only paths, and in some products leak privileged responses, so affected AJP front ends should not be dismissed as theoretical.
What to do — in priority order.
- Disable unused
mod_proxy_ajp— If you are not deliberately proxying AJP, remove or unload the module and close the finding as not affected. For a LOW verdict there is no SLA clock here; do it as backlog hygiene during normal config maintenance. - Remove
ajp://routes — Search Apache configs forProxyPass,BalancerMember, and related directives pointing toajp://. If AJP is still present for legacy reasons, plan migration to HTTP/HTTPS proxying in the normal maintenance stream; that removes the exploit precondition entirely. - Bind backend AJP listeners tightly — Where AJP must remain, ensure the backend connector is restricted to loopback or tightly controlled internal interfaces and not shared broadly across tiers. That does not fix the frontend parsing bug, but it reduces accidental blast radius while you clean up the architecture.
- Stop trusting frontend-only controls — Review backend applications that rely on the Apache layer for path restrictions, IP allowlists, or auth-context enforcement. Request smuggling bugs are dangerous specifically because they can invalidate proxy-boundary assumptions; fold this review into the same backlog-hygiene work.
- A version-only exception policy does not help by itself; it hides whether
mod_proxy_ajpis actually present and can just replace one bad assumption with another. - A generic EDR deployment does little for the initial exploit path because the abuse happens in HTTP/AJP parsing and proxy behavior, not a dropped binary or post-exec payload.
- A WAF as a blanket answer is unreliable here; request smuggling lives in parser disagreement, and upstream normalization can help or miss depending on exact traffic path.
Crowdsourced verification payload.
Run this on the target Apache host, not from an auditor workstation. Invoke it with sudo bash check-cve-2022-26377.sh; root is preferred so it can read Apache configs and package metadata. It prints exactly one of VULNERABLE, PATCHED, or UNKNOWN and exits 1, 0, or 2 respectively.
#!/usr/bin/env bash
# check-cve-2022-26377.sh
# Determine practical exposure to CVE-2022-26377 (Apache mod_proxy_ajp request smuggling)
# Exit codes: 0=PATCHED/not affected, 1=VULNERABLE, 2=UNKNOWN
set -u
patched() {
echo "PATCHED"
exit 0
}
vulnerable() {
echo "VULNERABLE"
exit 1
}
unknown() {
echo "UNKNOWN"
exit 2
}
have_cmd() {
command -v "$1" >/dev/null 2>&1
}
ver_lt() {
# returns 0 if $1 < $2
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" != "$2" ] && return 1
[ "$1" != "$2" ]
}
APACHECTL=""
for c in apachectl apache2ctl; do
if have_cmd "$c"; then
APACHECTL="$c"
break
fi
done
HTTPD_BIN=""
for c in httpd apache2; do
if have_cmd "$c"; then
HTTPD_BIN="$c"
break
fi
done
if [ -z "$APACHECTL" ] && [ -z "$HTTPD_BIN" ]; then
unknown
fi
MODULES_OUT=""
if [ -n "$APACHECTL" ]; then
MODULES_OUT="$($APACHECTL -M 2>/dev/null || true)"
fi
module_loaded=0
printf '%s\n' "$MODULES_OUT" | grep -Eq 'proxy_ajp_module' && module_loaded=1
CONFIG_HITS=""
for d in /etc/httpd /etc/apache2 /usr/local/apache2/conf; do
if [ -d "$d" ]; then
HITS=$(grep -RniE '(^|[[:space:]])LoadModule[[:space:]]+proxy_ajp_module|ajp://|ProxyPass|ProxyPassMatch|BalancerMember' "$d" 2>/dev/null || true)
if [ -n "$HITS" ]; then
CONFIG_HITS+="$HITS"$'\n'
fi
fi
done
if [ $module_loaded -eq 0 ]; then
printf '%s\n' "$CONFIG_HITS" | grep -Eq 'LoadModule[[:space:]]+proxy_ajp_module' && module_loaded=1
fi
ajp_in_use=0
printf '%s\n' "$CONFIG_HITS" | grep -Eqi 'ajp://' && ajp_in_use=1
# If the module is absent or no AJP routes exist, this host is not practically exposed.
if [ $module_loaded -eq 0 ] || [ $ajp_in_use -eq 0 ]; then
patched
fi
# Package-manager backport checks first.
if have_cmd dpkg-query; then
. /etc/os-release 2>/dev/null || true
PKGVER=$(dpkg-query -W -f='${Version}' apache2 2>/dev/null || true)
if [ -n "$PKGVER" ]; then
case "${VERSION_CODENAME:-}" in
jammy)
dpkg --compare-versions "$PKGVER" ge '2.4.52-1ubuntu4.1' && patched
;;
focal)
dpkg --compare-versions "$PKGVER" ge '2.4.41-4ubuntu3.12' && patched
;;
bionic)
dpkg --compare-versions "$PKGVER" ge '2.4.29-1ubuntu4.24' && patched
;;
xenial)
dpkg --compare-versions "$PKGVER" ge '2.4.18-2ubuntu3.17+esm6' && patched
;;
trusty)
dpkg --compare-versions "$PKGVER" ge '2.4.7-1ubuntu4.22+esm5' && patched
;;
bullseye)
dpkg --compare-versions "$PKGVER" ge '2.4.54-1~deb11u1' && patched
;;
buster)
dpkg --compare-versions "$PKGVER" ge '2.4.38-3+deb10u8' && patched
;;
esac
fi
fi
if have_cmd rpm; then
if rpm -q httpd >/dev/null 2>&1; then
rpm -q --changelog httpd 2>/dev/null | grep -Eqi 'CVE-2022-26377|mod_proxy_ajp: Possible request smuggling' && patched
fi
fi
# Fallback to upstream Apache version check.
VERSION_LINE=""
if [ -n "$HTTPD_BIN" ]; then
VERSION_LINE="$($HTTPD_BIN -v 2>/dev/null | grep -E 'Server version|Apache/' | head -n1 || true)"
elif [ -n "$APACHECTL" ]; then
VERSION_LINE="$($APACHECTL -v 2>/dev/null | grep -E 'Server version|Apache/' | head -n1 || true)"
fi
UPSTREAM_VER=$(printf '%s\n' "$VERSION_LINE" | sed -n 's/.*Apache\/\([0-9][0-9.]*\).*/\1/p' | head -n1)
if [ -z "$UPSTREAM_VER" ]; then
unknown
fi
if ver_lt "$UPSTREAM_VER" '2.4.54'; then
vulnerable
else
patched
fi
If you remember one thing.
mod_proxy_ajp or have no ajp:// routes as not affected; second, keep the small set of real AJP reverse proxies in backlog hygiene and remove or patch them during normal change windows. For this LOW verdict there is no noisgate mitigation SLA and no noisgate remediation SLA — treat it as backlog hygiene, but do the scoping work now so version-only noise does not hide the few genuinely exposed internet-facing AJP front ends.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.