Skip to content

Commit

Permalink
examples/http_filter: Add pointer offset accounting for variable ip h…
Browse files Browse the repository at this point in the history
…eader len (iovisor#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(
  ...
)
```
  • Loading branch information
ChaosData authored and yonghong-song committed Jul 19, 2018
1 parent 4e4c9e0 commit 3d9b687
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 7 deletions.
18 changes: 13 additions & 5 deletions examples/networking/http_filter/http-parse-complete.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
12 changes: 10 additions & 2 deletions examples/networking/http_filter/http-parse-simple.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 3d9b687

Please sign in to comment.