This is a pressure valve problem, not a front-door master key
Tenable plugin 118956 rolls up three nginx flaws fixed on 2018-11-06 in 1.14.1 and 1.15.6: two HTTP/2 resource-exhaustion bugs (CVE-2018-16843, CVE-2018-16844) and one ngx_http_mp4_module crash/memory-disclosure bug (CVE-2018-16845). The HTTP/2 issues affect 1.9.5-1.15.5 only when nginx is built with ngx_http_v2_module and a listen ... http2 path is actually configured; the MP4 issue affects 1.1.3-1.15.5 plus 1.0.7-1.0.15 only when nginx is built with ngx_http_mp4_module, the mp4 directive is used, and a crafted MP4 can be made to flow through that code path.
The MEDIUM label is basically right in enterprise reality. NVD's 7.5 HIGH for the HTTP/2 pair assumes a clean unauthenticated network DoS path, but real deployments add friction: optional build flags, specific config directives, and impact that is generally availability degradation on one web tier node, not takeover. Public internet reachability keeps this above LOW, but lack of KEV/active-exploitation evidence and the feature-gated attack surface keep it well below HIGH.
4 steps from start to impact.
Find a listener that actually exposes the vulnerable feature
curl, nghttp, or nmap/http2 probes for the HTTP/2 path, and ordinary content discovery for the MP4 path. This matters because version-only findings overstate exposure when the vulnerable module is present in code but not reachable in config.- Internet or internal network path to the nginx listener
- For CVE-2018-16843/16844: HTTP/2 enabled on a live
listensocket - For CVE-2018-16845: MP4 content routed through
ngx_http_mp4_module
- Upstream advisories state both
ngx_http_v2_moduleandngx_http_mp4_moduleare not built by default - Many scanners only read the
Serverheader and do not verifyhttp2ormp4directives - Distro backports can make old-looking package versions patched
http2 or mp4 is actually enabled. Local config audit or nginx -T review is needed.Trigger the HTTP/2 exhaustion path with frame abuse
nghttp/h2load) to send crafted frame patterns that drive excessive memory or excessive CPU consumption. The vendor advisory ties both flaws directly to the HTTP/2 implementation and an enabled listen ... http2 configuration. This is unauthenticated and remote once the feature is exposed.- nginx version in the vulnerable HTTP/2 range
ngx_http_v2_modulepresentlistenpath configured forhttp2
- Only availability is at stake; there is no code execution path here
- Reverse proxies, autoscaling, and health-checked load balancers can dilute single-node impact
- Rate limiting, connection caps, or upstream CDN buffering can reduce attacker efficiency
Starve workers and degrade the web tier
- Sustained request path to the targeted listener
- Insufficient headroom or weak admission controls on the affected tier
- Modern load balancers can drain sick nodes quickly
- CDNs and WAFs sometimes terminate HTTP/2 before nginx ever sees malicious frames
- Autoscaling can mask the effect even if the bug is real
Alternate path: feed a crafted MP4 into ngx_http_mp4_module
ffmpeg plus hex editing—and causes nginx to process it through the mp4 directive path. Per nginx, this can cause an infinite loop, worker crash, or worker-memory disclosure. In practice this path is narrower than the HTTP/2 pair because it requires both the module and a content-processing workflow that many enterprises do not enable.- Vulnerable version range for the MP4 bug
ngx_http_mp4_modulepresentmp4directive used on attacker-reachable content- Attacker can upload, place, or otherwise trigger processing of a crafted MP4
- This is a specific application workflow, not a generic nginx exposure
- Many orgs serve static media from object storage/CDN instead of nginx
mp4processing - Upload validation or media re-encoding often breaks the crafted file before nginx sees it
The supporting signals.
| In-the-wild status | I found no CISA KEV listing and no authoritative source in this review showing active exploitation campaigns. Treat this as no proven active exploitation evidence found, not as proof of absence. |
|---|---|
| Proof-of-concept availability | cvefeed.io reports 23 public GitHub PoCs for CVE-2018-16843, 18 for CVE-2018-16844, and 20 for CVE-2018-16845. The original nginx vendor material published advisories and an MP4 patch, not a weaponized exploit. |
| Reporter / researcher | nginx credits Gal Goldshtein of F5 Networks for the initial report of the HTTP/2 CPU issue in the advisory for CVE-2018-16844. |
| EPSS snapshot | Mirror data surfaced via Vulners shows EPSS approximately 0.58348 for CVE-2018-16843, 0.10883 for CVE-2018-16844, and 0.06332 for CVE-2018-16845. Use with caution: EPSS is probability, not impact, and mirrors may lag FIRST slightly. |
| KEV status | No matching CVE entries surfaced from the CISA KEV catalog during this assessment. |
| CVSS disagreement | NVD scores the HTTP/2 bugs at 7.5 HIGH (AV:N/AC:L/PR:N/UI:N/A:H), while Red Hat/CNA scored them 5.3 MEDIUM. For CVE-2018-16845, NVD shows 6.1 MEDIUM while Red Hat/CNA shows **8.2 HIGH`; that spread is a signal that exploit preconditions materially change the practical risk. |
| Affected versions | Per nginx advisories: HTTP/2 issues hit 1.9.5-1.15.5; MP4 issue hits 1.1.3-1.15.5 and 1.0.7-1.0.15. All three are fixed in 1.14.1 and 1.15.6 for upstream nginx. |
| Fixed versions and backports | Upstream fix is 1.14.1 / 1.15.6. Debian backported fixes to stretch 1.10.3-1+deb9u2; Ubuntu backported to 18.10 1.15.5-0ubuntu2.1, 18.04 LTS 1.14.0-0ubuntu1.2, 16.04 LTS 1.10.3-0ubuntu0.16.04.3, and 14.04 LTS 1.4.6-1ubuntu3.9. |
| Exposure population | This matters because nginx is everywhere: Netcraft's November 2018 survey put nginx at 25.53% of the top million busiest sites and 27.40% of active sites. Broad product prevalence justifies watching it, but the vulnerable *feature path* is still narrower than the product footprint. |
| Scanner caveat | Tenable plugin 118956 is a remote, header/version-based finding. That is good for fleet discovery, but weak for deciding urgency because it does not prove the target actually enables http2 or mp4, and it can overfire on backported distro packages. |
noisgate verdict.
The decisive factor is attack-path friction: every path here is gated by optional nginx features, and the dominant impact is denial of service, not code execution or privilege gain. Public exposure keeps the issue relevant, but there is no strong evidence in these sources that attackers are actively prioritizing this bug set in the wild.
Why this verdict
- Publicly reachable but mostly DoS-only — the HTTP/2 path can be hit remotely without auth, but the practical consequence is service degradation or worker exhaustion, not host compromise.
- Feature-gated exposure — CVE-2018-16843/16844 require
ngx_http_v2_module*and* a livelisten ... http2config; CVE-2018-16845 additionally requiresngx_http_mp4_module, an activemp4directive, and an attacker-reachable crafted MP4 workflow. - Version-only scanners overstate risk — Tenable detects by
Serverheader/version and cannot prove the vulnerable code path is reachable; that creates a lot of false urgency in distro-backported or feature-disabled estates.
Why not higher?
It is not HIGH because the chain lacks a strong amplifier like RCE, auth bypass, or tenant-wide compromise. The main HTTP/2 bugs are resource-consumption flaws, and the MP4 issue needs a narrow media-processing path that many enterprises simply do not expose.
Why not lower?
It is not LOW because nginx is massively deployed and internet-facing, and the HTTP/2 path can be reached by unauthenticated remote attackers when enabled. Even a DoS-only flaw matters on revenue-facing edge tiers, especially if you have concentrated ingress through a small number of reverse proxies.
What to do — in priority order.
- Validate feature reachability before escalating — Run a local config audit now to determine whether affected hosts actually enable
http2ormp4. For a MEDIUM verdict there is no mitigation SLA; use this check to separate real exposure from version-only noise and go straight into the remediation queue. - Disable unused HTTP/2 listeners — If you do not need HTTP/2 on a given edge tier, remove
http2fromlistenstatements or terminate HTTP/2 upstream at the CDN/load balancer instead. This meaningfully cuts the only broad unauthenticated path while you work through the 365-day remediation window. - Remove
mp4processing where possible — If themp4directive is present, move media serving to static delivery or a CDN/object store path and stop sending attacker-controlled MP4s through nginx parsing logic. That neutralizes the narrowest but messiest path without waiting for a binary upgrade. - Cap abusive connection behavior at the edge — Use CDN, reverse proxy, or load balancer controls for connection/request concurrency and per-client rate limits to reduce the impact of resource-exhaustion attempts. This is compensating hardening, not a substitute for patching, and for MEDIUM there is no mitigation SLA forcing an emergency change.
- Watch for backport false positives — Before creating mass work orders, reconcile package versions against distro advisories such as Debian and Ubuntu backports. Many old-looking versions are already fixed, and wasting change windows on those is how patch programs lose credibility.
- A generic WAF rule is not a reliable answer; these bugs live in protocol handling and module logic, so signature coverage is inconsistent and often bypassable.
- MFA does nothing here because the reachable path is on the web server itself, not an authenticated admin workflow.
- Header stripping or banner hiding only blinds scanners and defenders; it does not remove the vulnerable code path.
Crowdsourced verification payload.
Run this on the target nginx host as a local audit, not from your scanner. Invoke it with sudo bash ./check_nginx_118956.sh; it needs permission to run nginx -V and nginx -T so it can inspect build flags and effective config. It returns VULNERABLE, PATCHED, or UNKNOWN and exits non-zero only for VULNERABLE.
#!/usr/bin/env bash
# check_nginx_118956.sh
# Assess exposure for Tenable plugin 118956 / nginx CVE-2018-16843, -16844, -16845
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
have_cmd() { command -v "$1" >/dev/null 2>&1; }
semver_ge() {
[ "$1" = "$2" ] && return 0
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -n1)" = "$1" ]
}
semver_lt() {
[ "$1" = "$2" ] && return 1
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]
}
pkg_version_ge() {
# Compare distro package versions if dpkg or rpm is available
local a="$1" b="$2"
if have_cmd dpkg --compare-versions 1 1 >/dev/null 2>&1; then
dpkg --compare-versions "$a" ge "$b"
return $?
fi
if have_cmd rpm; then
rpm --quiet --eval '%{?dist}' >/dev/null 2>&1
[ "$(printf '%s\n%s\n' "$a" "$b" | sort -V | tail -n1)" = "$a" ]
return $?
fi
return 1
}
status="UNKNOWN"
reasons=()
if ! have_cmd nginx; then
echo "UNKNOWN: nginx binary not found in PATH"
exit 2
fi
nginx_v_raw="$(nginx -V 2>&1)"
nginx_t_raw="$(nginx -T 2>&1)"
nginx_ver="$(printf '%s' "$nginx_v_raw" | sed -n 's/^nginx version: nginx\/\([0-9][0-9.]*\).*$/\1/p' | head -n1)"
if [ -z "$nginx_ver" ]; then
echo "UNKNOWN: unable to parse nginx version from 'nginx -V'"
exit 2
fi
http2_compiled=0
mp4_compiled=0
printf '%s' "$nginx_v_raw" | grep -Eq 'http_v2_module' && http2_compiled=1
printf '%s' "$nginx_v_raw" | grep -Eq 'http_mp4_module' && mp4_compiled=1
http2_enabled=0
mp4_enabled=0
printf '%s\n' "$nginx_t_raw" | grep -Eiq '^[[:space:]]*listen[[:space:]].*http2([;[:space:]]|$)|^[[:space:]]*http2[[:space:]]+on[[:space:]]*;' && http2_enabled=1
printf '%s\n' "$nginx_t_raw" | grep -Eiq '^[[:space:]]*mp4[[:space:]]*;' && mp4_enabled=1
# Distro package version checks for common backports
pkg_name=""
pkg_ver=""
if have_cmd dpkg-query; then
for p in nginx nginx-core nginx-full nginx-light nginx-extras nginx-common; do
if dpkg-query -W -f='${Status} ${Version}\n' "$p" 2>/dev/null | grep -q '^install ok installed '; then
pkg_name="$p"
pkg_ver="$(dpkg-query -W -f='${Version}' "$p" 2>/dev/null)"
break
fi
done
elif have_cmd rpm; then
if rpm -q nginx >/dev/null 2>&1; then
pkg_name="nginx"
pkg_ver="$(rpm -q --qf '%{VERSION}-%{RELEASE}' nginx 2>/dev/null)"
fi
fi
backport_patched=0
if [ -n "$pkg_ver" ]; then
case "$pkg_ver" in
*1.10.3-1+deb9u2*|*1.10.3-1+deb9u3*|*1.10.3-0ubuntu0.16.04.3*|*1.14.0-0ubuntu1.2*|*1.15.5-0ubuntu2.1*|*1.4.6-1ubuntu3.9*)
backport_patched=1
;;
esac
fi
http2_range_vuln=0
mp4_range_vuln=0
# HTTP/2 affected: 1.9.5-1.15.5; fixed in 1.14.1 and 1.15.6
if semver_ge "$nginx_ver" "1.9.5"; then
if semver_lt "$nginx_ver" "1.14.1"; then
http2_range_vuln=1
elif semver_ge "$nginx_ver" "1.15.0" && semver_lt "$nginx_ver" "1.15.6"; then
http2_range_vuln=1
fi
fi
# MP4 affected: 1.1.3-1.15.5 and 1.0.7-1.0.15; fixed in 1.14.1 and 1.15.6
if semver_ge "$nginx_ver" "1.1.3"; then
if semver_lt "$nginx_ver" "1.14.1"; then
mp4_range_vuln=1
elif semver_ge "$nginx_ver" "1.15.0" && semver_lt "$nginx_ver" "1.15.6"; then
mp4_range_vuln=1
fi
elif semver_ge "$nginx_ver" "1.0.7" && semver_lt "$nginx_ver" "1.0.16"; then
mp4_range_vuln=1
fi
if [ "$backport_patched" -eq 1 ]; then
echo "PATCHED: distro package backport detected (${pkg_name} ${pkg_ver})"
exit 0
fi
http2_reachable=0
mp4_reachable=0
[ "$http2_range_vuln" -eq 1 ] && [ "$http2_compiled" -eq 1 ] && [ "$http2_enabled" -eq 1 ] && http2_reachable=1
[ "$mp4_range_vuln" -eq 1 ] && [ "$mp4_compiled" -eq 1 ] && [ "$mp4_enabled" -eq 1 ] && mp4_reachable=1
if [ "$http2_reachable" -eq 1 ] || [ "$mp4_reachable" -eq 1 ]; then
echo "VULNERABLE: nginx ${nginx_ver} with reachable vulnerable path(s): HTTP2=${http2_reachable} MP4=${mp4_reachable}"
echo "DETAIL: compiled_http2=${http2_compiled} enabled_http2=${http2_enabled} compiled_mp4=${mp4_compiled} enabled_mp4=${mp4_enabled}"
exit 1
fi
# Not in vulnerable range, or features not reachable
if [ "$http2_range_vuln" -eq 0 ] && [ "$mp4_range_vuln" -eq 0 ]; then
echo "PATCHED: nginx ${nginx_ver} is outside the upstream vulnerable ranges"
exit 0
fi
if [ "$http2_range_vuln" -eq 1 ] || [ "$mp4_range_vuln" -eq 1 ]; then
echo "PATCHED: nginx ${nginx_ver} is in a nominal vulnerable version range, but no reachable vulnerable config was found (HTTP2 compiled=${http2_compiled}, enabled=${http2_enabled}; MP4 compiled=${mp4_compiled}, enabled=${mp4_enabled})"
exit 0
fi
echo "UNKNOWN: insufficient data to determine exposure"
exit 2
If you remember one thing.
http2 or mp4; if they do, queue them for normal remediation and clean up unnecessary feature exposure during standard change windows. For a MEDIUM verdict there is no noisgate mitigation SLA — go straight to the 365-day remediation window; the noisgate remediation SLA is ≤365 days. If you discover a small set of revenue-critical edge nodes with live HTTP/2 exposure, patch those earlier as an availability-hardening task, but this is still not an emergency patch-everything event.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.