← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
tenable:193422 · CWE-444 · Disclosed 2022-06-08

Apache 2

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

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.

"Version-only scanners overcall this one; the real risk exists only on Apache front ends actually proxying AJP."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Find an externally reachable Apache front end

The attacker starts with a public-facing Apache HTTP Server instance flagged by bannering, package inventory, or scanner data such as Nessus plugin 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.
Conditions required:
  • Apache HTTP Server is reachable from the attacker
  • The instance is running a version in the affected range or appears to be
Where this breaks in practice:
  • Banner/package version alone does not show whether mod_proxy_ajp is loaded
  • Distro backports can make an old-looking package non-vulnerable
  • Many Apache servers are not reverse proxies at all
Detection/coverage: Excellent scanner coverage for version discovery; poor coverage for the configuration prerequisite. Nessus 193422 is fundamentally a version-based finding.
STEP 02

Confirm mod_proxy_ajp is actually in the request path

To exploit this CVE, the attacker needs Apache to be acting as an AJP-speaking reverse proxy. Public PoC material includes the watchTowr QRadar AJP smuggling work and associated GitHub tooling. Without a live ajp:// backend route, the bug is inert in practice.
Conditions required:
  • mod_proxy_ajp is loaded
  • Apache is configured with ProxyPass, balancer members, or equivalent routes to an AJP backend
  • The vulnerable frontend path is attacker-reachable
Where this breaks in practice:
  • 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
Detection/coverage: Weak from external scanners. Best detection is local config review, module inventory, or EDR/CMDB-backed configuration inspection.
STEP 03

Desync Apache and the AJP backend

The attacker sends a crafted request that Apache and the downstream AJP server interpret differently, smuggling a second request through the proxy boundary. Tools are typically custom Python scripts or the watchTowr QRadar PoC lineage rather than mass-exploitation kits. The goal is to make the backend process traffic that the frontend thought it had already normalized or bounded.
Conditions required:
  • A compatible request path exists through the vulnerable AJP proxy flow
  • Frontend and backend parsing differences are reachable with attacker-controlled input
Where this breaks in practice:
  • 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
Detection/coverage: Partial coverage from WAF/proxy anomaly logging and HTTP parser errors, but many detections are heuristic and request-smuggling signatures are inconsistent.
STEP 04

Abuse backend trust assumptions

Once smuggling works, the attacker can target protected backend paths, poison response queues, or bypass assumptions enforced only at the frontend proxy layer. watchTowr demonstrated this against IBM QRadar to leak privileged responses to unauthenticated users. That is real impact, but it is still application-path and trust-model dependent, not universal host compromise.
Conditions required:
  • 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
Where this breaks in practice:
  • 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
Detection/coverage: Application logs may show impossible request sequences, mismatched authentication context, or backend-only paths being hit from frontend clients.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo reviewed source showed CISA KEV inclusion or vendor-confirmed broad active exploitation. Public exploitation discussion is mainly research-driven, not mass abuse.
PoC availabilityYes. watchTowr published technical research and linked a GitHub PoC/detection-artifact generator: watchtowrlabs/ibm-qradar-ajp_smuggling_CVE-2022-26377_poc.
EPSS0.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 statusNot listed in the CISA Known Exploited Vulnerabilities catalog page reviewed.
CVSS vectorCVSS: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 versionsUpstream 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 versionsUpstream 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 realityInternet-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 timelineApache 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 notesUpstream credits Ricter Z @ 360 Noah Lab. Later public weaponization and impact demonstration came from watchTowr, notably against IBM QRadar.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.4/10)

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.

HIGH Affected-version and fixed-version mapping
HIGH Assessment that version-only scanner counts materially overstate exposure
MEDIUM Population estimate for how many enterprise Apache deployments still proxy AJP externally

Why this verdict

  • Strong config gate: the NVD 7.5 baseline assumes a network bug, but real exploitation requires mod_proxy_ajp plus 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 193422 keys 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.

05 · Compensating Control

What to do — in priority order.

  1. 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.
  2. Remove ajp:// routes — Search Apache configs for ProxyPass, BalancerMember, and related directives pointing to ajp://. 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.
  3. 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.
  4. 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.
What doesn't work
  • A version-only exception policy does not help by itself; it hides whether mod_proxy_ajp is 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.
06 · Verification

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.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/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
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, split Tenable 193422 into two buckets instead of patching by banner: first, close hosts that do not load 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

  1. Tenable Nessus Plugin 193422
  2. Apache HTTP Server 2.4 vulnerabilities
  3. oss-security disclosure for CVE-2022-26377
  4. NVD entry for CVE-2022-26377
  5. Ubuntu CVE tracker for CVE-2022-26377
  6. Debian security tracker for CVE-2022-26377
  7. watchTowr QRadar AJP smuggling research
  8. CISA Known Exploited Vulnerabilities Catalog
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.