Remove mod_http2/mod_md from Apache images + build gate (CVE-2026-119618) #39
No files matched your search
@@ -56,6 +56,7 @@ jobs:
|
|||||||
scripts/lsphp-src-overlay.sh \
|
scripts/lsphp-src-overlay.sh \
|
||||||
scripts/lsphp-abi-gate.sh \
|
scripts/lsphp-abi-gate.sh \
|
||||||
scripts/tune-mpm.sh \
|
scripts/tune-mpm.sh \
|
||||||
|
scripts/httpd-h2-md-gate.sh \
|
||||||
scripts/tests/lsphp-info-probe.test.sh \
|
scripts/tests/lsphp-info-probe.test.sh \
|
||||||
scripts/lsphp-repo-version.sh \
|
scripts/lsphp-repo-version.sh \
|
||||||
scripts/tests/lsphp-repo-version.test.sh \
|
scripts/tests/lsphp-repo-version.test.sh \
|
||||||
|
|||||||
@@ -89,6 +89,12 @@ COPY ./configs/whp-security.conf /etc/httpd/conf.d/
|
|||||||
# Set up cron job in a single layer
|
# Set up cron job in a single layer
|
||||||
RUN echo "15 */12 * * * root /scripts/log-rotate.sh" >> /etc/crontab
|
RUN echo "15 */12 * * * root /scripts/log-rotate.sh" >> /etc/crontab
|
||||||
|
|
||||||
|
# CVE-2026-119618 defense in depth: no HTTP/2 / mod_md in the image, build fails
|
||||||
|
# if they come back or the config no longer parses. scripts/httpd-h2-md-gate.sh.
|
||||||
|
# Placed after every other package step so nothing later can re-add them.
|
||||||
|
RUN /scripts/httpd-h2-md-gate.sh remove && /scripts/httpd-h2-md-gate.sh check
|
||||||
|
LABEL org.whp.httpd-h2-md="removed"
|
||||||
|
|
||||||
## Healthy = Apache answered with anything but a 5xx. `curl -f` also failed on
|
## Healthy = Apache answered with anything but a 5xx. `curl -f` also failed on
|
||||||
## 4xx, so a new site with an empty docroot (403) or an app with no route for /
|
## 4xx, so a new site with an empty docroot (403) or an app with no route for /
|
||||||
## (404) showed unhealthy forever, and WHP's monitor restarted it as "PHP
|
## (404) showed unhealthy forever, and WHP's monitor restarted it as "PHP
|
||||||
|
|||||||
@@ -83,6 +83,11 @@ RUN sed -i "s/rhel\$releasever-amd64/rhel\$releasever-$(uname -m | sed s/x86_64/
|
|||||||
# Set up cron job for log rotation
|
# Set up cron job for log rotation
|
||||||
RUN echo "15 */12 * * * root /scripts/log-rotate.sh" >> /etc/crontab
|
RUN echo "15 */12 * * * root /scripts/log-rotate.sh" >> /etc/crontab
|
||||||
|
|
||||||
|
# CVE-2026-119618: this image carries httpd-core only (no mod_http2/mod_md). The
|
||||||
|
# gate keeps it that way and records the version in /etc/whp-httpd-version.
|
||||||
|
RUN /scripts/httpd-h2-md-gate.sh remove && /scripts/httpd-h2-md-gate.sh check
|
||||||
|
LABEL org.whp.httpd-h2-md="removed"
|
||||||
|
|
||||||
EXPOSE 9000
|
EXPOSE 9000
|
||||||
|
|
||||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ COPY ./scripts/log-rotate.sh /scripts/log-rotate.sh
|
|||||||
COPY ./scripts/entrypoint-shared-httpd.sh /scripts/entrypoint-shared-httpd.sh
|
COPY ./scripts/entrypoint-shared-httpd.sh /scripts/entrypoint-shared-httpd.sh
|
||||||
COPY ./scripts/stop-services.sh /scripts/stop-services.sh
|
COPY ./scripts/stop-services.sh /scripts/stop-services.sh
|
||||||
COPY ./scripts/tune-mpm.sh /scripts/tune-mpm.sh
|
COPY ./scripts/tune-mpm.sh /scripts/tune-mpm.sh
|
||||||
|
COPY ./scripts/httpd-h2-md-gate.sh /scripts/httpd-h2-md-gate.sh
|
||||||
RUN chmod +x /scripts/*
|
RUN chmod +x /scripts/*
|
||||||
|
|
||||||
# Generate self-signed SSL cert (same as main CAC image)
|
# Generate self-signed SSL cert (same as main CAC image)
|
||||||
@@ -49,6 +50,12 @@ RUN mkdir -p /etc/httpd/conf.d/vhosts
|
|||||||
# Set up cron job for log rotation
|
# Set up cron job for log rotation
|
||||||
RUN echo "15 */12 * * * root /scripts/log-rotate.sh" >> /etc/crontab
|
RUN echo "15 */12 * * * root /scripts/log-rotate.sh" >> /etc/crontab
|
||||||
|
|
||||||
|
# CVE-2026-119618 defense in depth: no HTTP/2 / mod_md in the image, build fails
|
||||||
|
# if they come back or the config no longer parses. scripts/httpd-h2-md-gate.sh.
|
||||||
|
# Placed after every other package step so nothing later can re-add them.
|
||||||
|
RUN /scripts/httpd-h2-md-gate.sh remove && /scripts/httpd-h2-md-gate.sh check
|
||||||
|
LABEL org.whp.httpd-h2-md="removed"
|
||||||
|
|
||||||
EXPOSE 80 443
|
EXPOSE 80 443
|
||||||
|
|
||||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
|
||||||
|
|||||||
Executable
+55
@@ -0,0 +1,55 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# CVE-2026-119618 (mod_http2 assign_headers heap corruption, httpd 2.4.55-2.4.70)
|
||||||
|
# defense in depth. Nothing in WHP needs HTTP/2 or mod_md inside a container: the
|
||||||
|
# HAProxy edge terminates h2/h3 and speaks HTTP/1.1 to backends, and certificates
|
||||||
|
# come from the edge, not mod_md. So the modules are removed from every
|
||||||
|
# Alma-based Apache image and this gate fails the build if they ever come back.
|
||||||
|
#
|
||||||
|
# httpd-h2-md-gate.sh remove uninstall mod_http2 / mod_md RPMs (if present)
|
||||||
|
# httpd-h2-md-gate.sh check fail unless the modules cannot load, `httpd -t`
|
||||||
|
# passes, and record the httpd version
|
||||||
|
#
|
||||||
|
# Both are idempotent and safe on images with no Apache at all (a no-op).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BAD_MODULES='http2_module|proxy_http2_module|md_module'
|
||||||
|
MOD_PKGS='mod_http2 mod_md'
|
||||||
|
|
||||||
|
cmd_remove() {
|
||||||
|
local p present=()
|
||||||
|
for p in $MOD_PKGS; do
|
||||||
|
rpm -q "$p" >/dev/null 2>&1 && present+=("$p")
|
||||||
|
done
|
||||||
|
if [ "${#present[@]}" -gt 0 ]; then
|
||||||
|
dnf remove -y "${present[@]}"
|
||||||
|
fi
|
||||||
|
# Belt and braces if a package was removed but a module file was left behind.
|
||||||
|
rm -f /etc/httpd/conf.modules.d/10-h2.conf /etc/httpd/conf.modules.d/10-proxy_h2.conf \
|
||||||
|
/etc/httpd/conf.modules.d/*-md.conf \
|
||||||
|
/usr/lib64/httpd/modules/mod_http2.so /usr/lib64/httpd/modules/mod_proxy_http2.so \
|
||||||
|
/usr/lib64/httpd/modules/mod_md.so
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_check() {
|
||||||
|
local p mods v fail=0
|
||||||
|
command -v httpd >/dev/null 2>&1 || { echo "gate: no httpd binary" >&2; exit 1; }
|
||||||
|
for p in $MOD_PKGS; do
|
||||||
|
if rpm -q "$p" >/dev/null 2>&1; then echo "gate FAIL: RPM $p is installed" >&2; fail=1; fi
|
||||||
|
done
|
||||||
|
# Anchored on the module name column ("systemd_module" must NOT match md_module).
|
||||||
|
mods=$(httpd -M 2>/dev/null) || { echo "gate FAIL: httpd -M failed" >&2; exit 1; }
|
||||||
|
if printf '%s\n' "$mods" | grep -E "^ (${BAD_MODULES}) "; then
|
||||||
|
echo "gate FAIL: HTTP/2 or mod_md module still loadable" >&2; fail=1
|
||||||
|
fi
|
||||||
|
[ "$fail" -eq 0 ] || exit 1
|
||||||
|
httpd -t
|
||||||
|
v=$(rpm -q --qf '%{VERSION}-%{RELEASE}' httpd-core)
|
||||||
|
printf '%s\n' "$v" > /etc/whp-httpd-version
|
||||||
|
echo "gate OK: httpd-core ${v}; no http2/proxy_http2/md modules; httpd -t passes"
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
remove) cmd_remove ;;
|
||||||
|
check) cmd_check ;;
|
||||||
|
*) echo "usage: $0 remove|check" >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
Reference in new issue
Block a user