Commit 3d9b687d authored by ChaosData's avatar ChaosData Committed by yonghong-song

examples/http_filter: Add pointer offset accounting for variable ip header len (#1868)

This fix adds additional accounting logic to the http_filter examples ("simple"
and "complete") that make sure to shift the pointer for the IP body/payload to
the correct offset before accessing TCP header fields. This is done by taking
into account the IP header length field. Previously, the IP header length field
was used, but it was done later in processing, after TCP header values were
extracted using the size of the BCC `proto.h` `struct ip_t` a static offset.

Prior to this, it was possible to evade HTTP detection by injecting IP options
data into the IP header that would spoof parts of the TCP header and shift the
real one down, as done in the scapy snippet below:

```Python
IP(
  dst=target[0],
  options=struct.pack(">BBHHHB",130,11,8080,0,0,0),
)/TCP(
  ...
)
```
parent 4e4c9e01
......@@ -56,6 +56,19 @@ int http_filter(struct __sk_buff *skb) {
struct Key key;
struct Leaf zero = {0};
//calculate ip header length
//value to multiply * 4
//e.g. ip->hlen = 5 ; IP Header Length = 5 x 4 byte = 20 byte
ip_header_length = ip->hlen << 2; //SHL 2 -> *4 multiply
//check ip header length against minimum
if (ip_header_length < sizeof(*ip)) {
goto DROP;
}
//shift cursor forward for dynamic ip header size
void *_ = cursor_advance(cursor, (ip_header_length-sizeof(*ip)));
struct tcp_t *tcp = cursor_advance(cursor, sizeof(*tcp));
//retrieve ip src/dest and port src/dest of current packet
......@@ -65,11 +78,6 @@ int http_filter(struct __sk_buff *skb) {
key.dst_port = tcp->dst_port;
key.src_port = tcp->src_port;
//calculate ip header length
//value to multiply * 4
//e.g. ip->hlen = 5 ; IP Header Length = 5 x 4 byte = 20 byte
ip_header_length = ip->hlen << 2; //SHL 2 -> *4 multiply
//calculate tcp header length
//value to multiply *4
//e.g. tcp->offset = 5 ; TCP Header Length = 5 x 4 byte = 20 byte
......
......@@ -34,13 +34,21 @@ int http_filter(struct __sk_buff *skb) {
u32 payload_offset = 0;
u32 payload_length = 0;
struct tcp_t *tcp = cursor_advance(cursor, sizeof(*tcp));
//calculate ip header length
//value to multiply * 4
//e.g. ip->hlen = 5 ; IP Header Length = 5 x 4 byte = 20 byte
ip_header_length = ip->hlen << 2; //SHL 2 -> *4 multiply
//check ip header length against minimum
if (ip_header_length < sizeof(*ip)) {
goto DROP;
}
//shift cursor forward for dynamic ip header size
void *_ = cursor_advance(cursor, (ip_header_length-sizeof(*ip)));
struct tcp_t *tcp = cursor_advance(cursor, sizeof(*tcp));
//calculate tcp header length
//value to multiply *4
//e.g. tcp->offset = 5 ; TCP Header Length = 5 x 4 byte = 20 byte
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment