168 lines
2.8 KiB
Plaintext
168 lines
2.8 KiB
Plaintext
|
# This test ensures that h2 requests with invalid pseudo-headers are properly
|
||
|
# rejected. Also, the host header must be ignored if authority is present. This
|
||
|
# is necessary to avoid http/2 desync attacks through haproxy as described here
|
||
|
# https://portswigger.net/research/http2
|
||
|
|
||
|
varnishtest "h2 desync attacks"
|
||
|
feature ignore_unknown_macro
|
||
|
|
||
|
server s1 {
|
||
|
rxreq
|
||
|
expect req.http.host == "hostname"
|
||
|
txresp
|
||
|
} -start
|
||
|
|
||
|
# haproxy frontend
|
||
|
haproxy hap -conf {
|
||
|
defaults
|
||
|
mode http
|
||
|
|
||
|
listen feSrvH1
|
||
|
bind "fd@${feSrvH1}"
|
||
|
http-request return status 200
|
||
|
|
||
|
listen feSrvH2
|
||
|
bind "fd@${feSrvH2}" proto h2
|
||
|
http-request return status 200
|
||
|
|
||
|
listen fe1
|
||
|
bind "fd@${fe1}" proto h2
|
||
|
server srv-hapSrv "${hap_feSrvH1_addr}:${hap_feSrvH1_port}"
|
||
|
|
||
|
listen fe2
|
||
|
bind "fd@${fe2}" proto h2
|
||
|
server srv-hapSrv "${hap_feSrvH2_addr}:${hap_feSrvH2_port}" proto h2
|
||
|
|
||
|
listen fe3
|
||
|
bind "fd@${fe3}" proto h2
|
||
|
server s1 "${s1_addr}:${s1_port}"
|
||
|
} -start
|
||
|
|
||
|
# valid request
|
||
|
client c1 -connect ${hap_fe1_sock} {
|
||
|
txpri
|
||
|
stream 0 {
|
||
|
txsettings
|
||
|
rxsettings
|
||
|
txsettings -ack
|
||
|
rxsettings
|
||
|
expect settings.ack == true
|
||
|
} -run
|
||
|
|
||
|
stream 1 {
|
||
|
txreq \
|
||
|
-method "GET" \
|
||
|
-scheme "http" \
|
||
|
-url "/"
|
||
|
rxresp
|
||
|
expect resp.status == 200
|
||
|
} -run
|
||
|
} -run
|
||
|
|
||
|
# valid request
|
||
|
client c2 -connect ${hap_fe2_sock} {
|
||
|
txpri
|
||
|
stream 0 {
|
||
|
txsettings
|
||
|
rxsettings
|
||
|
txsettings -ack
|
||
|
rxsettings
|
||
|
expect settings.ack == true
|
||
|
} -run
|
||
|
|
||
|
stream 1 {
|
||
|
txreq \
|
||
|
-method "GET" \
|
||
|
-scheme "http" \
|
||
|
-url "/"
|
||
|
rxresp
|
||
|
expect resp.status == 200
|
||
|
} -run
|
||
|
} -run
|
||
|
|
||
|
# invalid path
|
||
|
client c3-path -connect ${hap_fe1_sock} {
|
||
|
txpri
|
||
|
stream 0 {
|
||
|
txsettings
|
||
|
rxsettings
|
||
|
txsettings -ack
|
||
|
rxsettings
|
||
|
expect settings.ack == true
|
||
|
} -run
|
||
|
|
||
|
stream 1 {
|
||
|
txreq \
|
||
|
-method "GET" \
|
||
|
-scheme "http" \
|
||
|
-url "hello-world"
|
||
|
rxrst
|
||
|
} -run
|
||
|
} -run
|
||
|
|
||
|
# invalid scheme
|
||
|
client c4-scheme -connect ${hap_fe1_sock} {
|
||
|
txpri
|
||
|
stream 0 {
|
||
|
txsettings
|
||
|
rxsettings
|
||
|
txsettings -ack
|
||
|
rxsettings
|
||
|
expect settings.ack == true
|
||
|
} -run
|
||
|
|
||
|
stream 1 {
|
||
|
txreq \
|
||
|
-method "GET" \
|
||
|
-scheme "http://localhost/?" \
|
||
|
-url "/"
|
||
|
rxresp
|
||
|
expect resp.status == 400
|
||
|
} -run
|
||
|
} -run
|
||
|
|
||
|
# invalid method
|
||
|
client c5-method -connect ${hap_fe2_sock} {
|
||
|
txpri
|
||
|
stream 0 {
|
||
|
txsettings
|
||
|
rxsettings
|
||
|
txsettings -ack
|
||
|
rxsettings
|
||
|
expect settings.ack == true
|
||
|
} -run
|
||
|
|
||
|
stream 1 {
|
||
|
txreq \
|
||
|
-method "GET?" \
|
||
|
-scheme "http" \
|
||
|
-url "/"
|
||
|
rxresp
|
||
|
expect resp.status == 400
|
||
|
} -run
|
||
|
} -run
|
||
|
|
||
|
# different authority and host headers
|
||
|
# in this case, host should be ignored in favor of the authority
|
||
|
client c6-host-authority -connect ${hap_fe3_sock} {
|
||
|
txpri
|
||
|
stream 0 {
|
||
|
txsettings
|
||
|
rxsettings
|
||
|
txsettings -ack
|
||
|
rxsettings
|
||
|
expect settings.ack == true
|
||
|
} -run
|
||
|
|
||
|
stream 1 {
|
||
|
txreq \
|
||
|
-method "GET" \
|
||
|
-scheme "http" \
|
||
|
-url "/" \
|
||
|
-hdr ":authority" "hostname" \
|
||
|
-hdr "host" "other_host"
|
||
|
} -run
|
||
|
} -run
|
||
|
|
||
|
server s1 -wait
|