diff options
Diffstat (limited to 'reg-tests/http-messaging/h2_desync_attacks.vtc')
-rw-r--r-- | reg-tests/http-messaging/h2_desync_attacks.vtc | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/reg-tests/http-messaging/h2_desync_attacks.vtc b/reg-tests/http-messaging/h2_desync_attacks.vtc new file mode 100644 index 0000000..112bc60 --- /dev/null +++ b/reg-tests/http-messaging/h2_desync_attacks.vtc @@ -0,0 +1,167 @@ +# 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 |