From a422f60a9a5feddeb0597bdf7d3e4b6c869cd204 Mon Sep 17 00:00:00 2001 From: _Frky <3105926+Frky@users.noreply.github.com> Date: Thu, 23 Dec 2021 11:03:40 +0100 Subject: [PATCH 1/2] Add test to emphasis bug in HTTP FSM --- src/proto/mod.rs | 30 +++++++++++++++++++++++++++++ test/src/all.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/src/proto/mod.rs b/src/proto/mod.rs index 9000eca..291002b 100644 --- a/src/proto/mod.rs +++ b/src/proto/mod.rs @@ -285,4 +285,34 @@ mod tests { }; } } + + #[test] + fn test_proto_repl_http() { + /* ensure that HTTP FSM does not answer until completion of request + * (at least headers) */ + let mut client_info = ClientInfo::new(); + let test_ip_addr = Ipv4Addr::new(3, 2, 1, 0); + client_info.ip.src = Some(IpAddr::V4(test_ip_addr)); + client_info.port.src = Some(65000); + let masscanned_ip_addr = Ipv4Addr::new(0, 1, 2, 3); + let mut ips = HashSet::new(); + ips.insert(IpAddr::V4(masscanned_ip_addr)); + /* Construct masscanned context object */ + let masscanned = Masscanned { + synack_key: [0, 0], + mac: MacAddr::from_str("00:11:22:33:44:55").expect("error parsing MAC address"), + iface: None, + ip_addresses: Some(&ips), + }; + /***** TEST COMPLETE REQUEST *****/ + let payload = b"GET / HTTP/1.1\r\n\r\n"; + if let None = repl(&payload.to_vec(), &masscanned, &mut client_info) { + panic!("expected an answer, got nothing"); + } + /***** TEST INCOMPLETE REQUEST *****/ + let payload = b"GET / HTTP/1.1\r\n"; + if let Some(_) = repl(&payload.to_vec(), &masscanned, &mut client_info) { + panic!("expected no answer, got one"); + } + } } diff --git a/test/src/all.py b/test/src/all.py index c73d65b..214a249 100644 --- a/test/src/all.py +++ b/test/src/all.py @@ -537,6 +537,56 @@ def test_ipv4_tcp_http(): assert tcp.payload.load.startswith(b"HTTP/1.1 401 Unauthorized\n") +@test +def test_ipv4_tcp_http_incomplete(): + sport = 24595 + dports = [80, 443, 5000, 53228] + for dport in dports: + seq_init = int(RandInt()) + syn = ( + Ether(dst=MAC_ADDR) + / IP(dst=IPV4_ADDR) + / TCP(flags="S", sport=sport, dport=dport, seq=seq_init) + ) + syn_ack = srp1(syn, timeout=1) + assert syn_ack is not None, "expecting answer, got nothing" + check_ip_checksum(syn_ack) + assert TCP in syn_ack, "expecting TCP, got %r" % syn_ack.summary() + syn_ack = syn_ack[TCP] + assert syn_ack.flags == "SA", "expecting TCP SA, got %r" % syn_ack.flags + ack = ( + Ether(dst=MAC_ADDR) + / IP(dst=IPV4_ADDR) + / TCP( + flags="A", + sport=sport, + dport=dport, + seq=seq_init + 1, + ack=syn_ack.seq + 1, + ) + ) + _ = srp1(ack, timeout=1) + req = ( + Ether(dst=MAC_ADDR) + / IP(dst=IPV4_ADDR) + / TCP( + flags="PA", + sport=sport, + dport=dport, + seq=seq_init + 1, + ack=syn_ack.seq + 1, + ) + # purposedly incomplete request (missing additionnal ending \r\n) + / Raw("GET / HTTP/1.1\r\n") + ) + resp = srp1(req, timeout=1) + assert resp is not None, "expecting an answer, got none" + check_ip_checksum(resp) + assert TCP in resp, "expecting TCP, got %r" % resp.summary() + tcp = resp[TCP] + assert tcp.flags == "A", "expecting TCP flag A, got {}".format(tcp.flags) + + @test def test_ipv6_tcp_http(): sport = 24592 From cffc94feb721cf5deedf4138d07784d6491a3fdc Mon Sep 17 00:00:00 2001 From: _Frky <3105926+Frky@users.noreply.github.com> Date: Thu, 23 Dec 2021 11:06:48 +0100 Subject: [PATCH 2/2] Fix bug in HTTP FSM --- src/proto/http.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/proto/http.rs b/src/proto/http.rs index a31f924..8879c54 100644 --- a/src/proto/http.rs +++ b/src/proto/http.rs @@ -232,6 +232,11 @@ pub fn repl<'a>( debug!("pstate: {}", pstate.state); return None; } + /* if not in CONTENT state, not responding yet (it means the client + * has not finished sending headers yet) */ + if pstate.state != HTTP_STATE_CONTENT { + return None; + } let content = "\ 401 Authorization Required