Browser h2 is not end-to-end HTTP/2: check the upstream hop

Started by Anoncto@anoncto••0 views•1 replies
A
Anoncto@anoncto
VIP
5
0
#1

Your browser can report h2 while the application behind the load balancer still receives HTTP/1.1. Those are different connections. If you are evaluating a request-smuggling mitigation, the upstream connection belongs in the picture too.

Where the downgrade happens

Plain text
browser -- HTTP/2 --> reverse proxy -- HTTP/1.1 --> application

The proxy terminates the client connection and translates the request for the next hop. PortSwigger's HTTP/2 downgrading explanation describes this conversion and the request-smuggling risks it can introduce.

That translation puts HTTP/1 request-boundary parsing back into the path. If the proxy and the receiving server disagree about where a request ends, the browser's HTTP/2 connection has not removed that boundary. Downgrading is a boundary to examine, not proof of a vulnerability.

A concrete example: AWS Application Load Balancer

AWS's target-group documentation says ALBs send requests to targets using HTTP/1.1 by default. HTTP/2 is a separate target-group protocol-version setting.

The HTTP rows of its compatibility matrix are worth reading together:

Incoming request Target-group protocol version Documented result
HTTP/1.1 HTTP/1.1 Success
HTTP/2 HTTP/1.1 Success
HTTP/1.1 HTTP/2 Error
HTTP/2 HTTP/2 Success

“Success” here is a protocol-compatibility outcome, not a security rating. The awkward row is HTTP/1.1 → HTTP/2: changing the target group is not a transparent upgrade for every client. AWS also requires an HTTPS listener, a forward action and instance or ip targets for HTTP/2 target groups.

Read the configured target hop

For an ALB you operate, the AWS CLI's describe-target-groups command exposes the relevant fields. Use a configured CLI identity in the correct account/region with permission to describe target groups, and replace the placeholder with your ALB ARN:

Bash / Shell
aws elbv2 describe-target-groups \
  --load-balancer-arn '<your-alb-arn>' \
  --query 'TargetGroups[].{Name:TargetGroupName,Protocol:Protocol,Version:ProtocolVersion}' \
  --output table

Read Version (HTTP1, HTTP2 or GRPC) separately from Protocol (HTTP/HTTPS for these target groups). Encryption to the target does not establish its HTTP version.

This read-only command lists associated groups and their configuration. Match the request's listener forwarding rule to the relevant target group before interpreting the result; the list does not identify which group handled an individual request. A further proxy behind that target is another hop to inspect.

I’d map that actual route before calling “HTTP/2 enabled” a desync mitigation. The browser indicator answers a narrower question.

If you've removed an HTTP/1.1 upstream hop from a service with mixed HTTP/1.1 and HTTP/2 clients, which compatibility constraint shaped the design, and how did you confirm the protocol on the actual request path?

0

Join the conversation!