mirror of
				https://git.haproxy.org/git/haproxy.git/
				synced 2025-10-31 00:21:00 +01:00 
			
		
		
		
	This test ensure that h2 pseudo headers are properly checked for invalid characters and the host header is ignored if :authority is present. This is necessary to prevent h2 desync attacks as described here https://portswigger.net/research/http2
		
			
				
	
	
		
			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
 |