[Bro-Dev] Logging TCP server banners

Pierre LALET pierre at droids-corp.org
Mon Feb 12 12:19:38 PST 2018


Hi everyone,

[This mail has been sent to bro@ first, but I think I might have more
luck (and answers) here. Sorry for the inconvenience to those who have
already read it.]

For a network recon framework I am working on (https://ivre.rocks/ --
for those interested), I would like to log each "TCP server banner"
Bro sees.

I call "TCP server banner" the first chunk of data a server sends,
before the client has sent data (if the client sends data before the
server, I don't want to log anything).

Here is what I have done so far (`PassiveRecon` is my module's name):

```
export {
        redef tcp_content_deliver_all_resp = T;
        
        [...]
}

[...]

event tcp_contents(c: connection, is_orig: bool, seq: count, contents: string)
        {
        if (! is_orig && seq == 1 && c$orig$num_pkts == 2)
                {
                Log::write(PassiveRecon::LOG, [$ts=c$start_time,
                                               $host=c$id$resp_h,
                                               $srvport=c$id$resp_p,
                                               $recon_type=TCP_SERVER_BANNER,
                                               $value=contents]);
                }
        }
```

Basically, I consider we have a "TCP server banner" when `is_orig` is
false, when `seq` equals 1 and when we have seen exactly two packets
from the client (which should be a SYN and the first ACK).

This solution generally works **but** I sometimes log a data chunk
when I should not, particularly if I have missed part of the
traffic.

As an example, the following Scapy script creates a PCAP file that
would trick my script into logging a "TCP server banner" while the
client has actually sent some data (and we have missed an ACK packet,
left as a comment in the script):

```
wrpcap("test.cap", [
    Ether() / IP(dst="1.2.3.4", src="5.6.7.8") /
    TCP(dport=80, sport=5678, flags="S", ack=0, seq=555678),
    Ether() / IP(src="1.2.3.4", dst="5.6.7.8") /
    TCP(sport=80, dport=5678, flags="SA", seq=111234, ack=555679),
    # Ether() / IP(dst="1.2.3.4", src="5.6.7.8") /
    # TCP(dport=80, sport=5678, flags="A", ack=111235, seq=555679),
    Ether() / IP(dst="1.2.3.4", src="5.6.7.8") /
    TCP(dport=80, sport=5678, flags="PA", ack=111235, seq=555679) / "DATA",
    Ether() / IP(src="1.2.3.4", dst="5.6.7.8") /
    TCP(sport=80, dport=5678, flags="PA", seq=111235, ack=555683) / "DATA"
])
```

Is there a way to know that I have not missed any packet from the
client and/or a way to know that the client has not sent any data on
the connection (like an equivalent of the `seq` parameter, but for the
`ack`)?

Also, when `seq` equals 1, am I certain that I have not missed any
packet from the server?

One more question: is there a better, cleaner, etc. way to do what I'm
trying to do?

Thanks a lot,

Pierre

-- 
Pierre
http://pierre.droids-corp.org/


More information about the bro-dev mailing list