Hello Netfilter Team,

I would like to propose this patch, that allows us to match a packet if
its IP header has the unused bit is set.

The unused bit i am talking about is the first bit in the fragmentation
flags that is described as unused and must be zero.

0        1    2    3  ...  16
+++++++++++++++++++++++++++++
| Unused | DF | MF | OFFSET |
+++++++++++++++++++++++++++++

Setting this bit is one of four very discrete techniques used in OS
fingerprinting as described in Ofir Arkin's (www.sys-security.com) article
"Unverified fields - a problems with firewalls and firewall
technology today".

In a nutshell one may send one packet with this bit set and see if this
bit is zeroed out or echoed back.

The same goes for TOS, DF bit (note that some OS's use DF bit in PMTU
discovery), Unused bit and invalid ICMP code with ICMP ECHO REQUEST

Using these 4 methods + others using icmp protocol we can make a quite
precise judgement on the remote OS as TCP/IP implementation differ.

I belive that to be a kind of security issue, as it helps in recognition
stage of every attack. This patch works for me.

The tool used for testing was sing 1.1 from sourceforge.net

sing -U <host>
-U sets this bit,

tcpdump hex dump in fragmentation offset field has 8000
which stands for 100 in the flags. 


Best regards,
Maciej Soltysiak

obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o

obj-$(CONFIG_IP_NF_MATCH_IPUNUSEDBIT) += ipt_ipunusedbit.o
Author: Maciej Soltysiak <[EMAIL PROTECTED]>
Status: experimental, works for me.

This option adds CONFIG_IP_NF_MATCH_IPUNUSEDBIT, 

  It allows you to filter packets with the unused bit in the fragmentation
  flags set.
  This unused bit is the first bit in the fragmentation flags.
  0   1    2    3 ...  
  +++++++++++++++ 
  | U | DF | MF |
  +++++++++++++++
  U - Unused bit. Can be used to do some very discrete OS fingerprinting,
      as described by Ofir Arkin (www.sys-security.com) in article
      "Unverified Fields - a problem with firewalls today".
  
Example:
  $ iptables -A INPUT -m ipunusedbit -j LOG --log-prefix "IP Unusedbit set: "
  $ iptables -A INPUT -m ipunusedbit -j DROP

CONFIG_IP_NF_MATCH_IPV4OPTIONS
IPUNUSEDBIT patch support
CONFIG_IP_NF_MATCH_IPUNUSEDBIT
  This option adds a IPUNUSEDBIT match.
  It allows you to filter packets with the unused bit in the fragmentation
  flags set.
  This unused bit is the first bit in the fragmentation flags.
  0   1    2    3 ...  
  +++++++++++++++ 
  | U | DF | MF |
  +++++++++++++++
  U - Unused bit. Can be used to do some very discrete OS fingerprinting,
      as described by Ofir Arkin (www.sys-security.com) in article
      "Unverified Fields - a problem with firewalls today".
  
  If you say Y here, you may try:
  iptables -A INPUT -m ipunusedbit -j LOG --log-prefix "IPunusedbit: "
 
  If you want to compile it as a module, say M here and read
  Documentation/modules.txt.  If unsure, say `N'.

  dep_tristate '  IPV4OPTIONS match support (EXPERIMENTAL)' 
CONFIG_IP_NF_MATCH_IPV4OPTIONS $CONFIG_IP_NF_IPTABLES
  dep_tristate '  IPUNUSEDBIT match support (EXPERIMENTAL)' 
CONFIG_IP_NF_MATCH_IPUNUSEDBIT $CONFIG_IP_NF_IPTABLES
diff -uNr original/linux/net/ipv4/netfilter/ipt_ipunusedbit.c 
linuxd/net/ipv4/netfilter/ipt_ipunusedbit.c
--- original/linux/net/ipv4/netfilter/ipt_ipunusedbit.c Thu Jan  1 07:30:00 1970
+++ linuxd/net/ipv4/netfilter/ipt_ipunusedbit.c Sat May 25 14:20:30 2002
@@ -0,0 +1,71 @@
+/*
+  This is a module which is used to match the unused bit in the ipv4 header.
+  This unused bit is the first bit in the fragmentation flags.
+  0   1    2    3 ...  
+  +++++++++++++++ 
+  | U | DF | MF |
+  +++++++++++++++
+  U - Unused bit. Can be used to do some very discrete OS fingerprinting,
+      as described by Ofir Arkin (www.sys-security.com) in article
+      "Unverified Fields - a problem with firewalls today".
+  
+  This file is distributed under the terms of the GNU General Public
+  License (GPL). Copies of the GPL can be obtained from:
+  ftp://prep.ai.mit.edu/pub/gnu/GPL
+
+  25-may-2002 Maciej Soltysiak <[EMAIL PROTECTED]> : initial development.
+*/
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/ip.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+MODULE_LICENSE("GPL");
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const void *matchinfo,
+      int offset,
+      const void *hdr,
+      u_int16_t datalen,
+      int *hotdrop)
+{
+       const struct iphdr *iph = skb->nh.iph;
+
+       return ntohs(iph->frag_off)>>15;
+}
+
+static int
+checkentry(const char *tablename,
+          const struct ipt_ip *ip,
+          void *matchinfo,
+          unsigned int matchsize,
+          unsigned int hook_mask)
+{
+       if (matchsize != IPT_ALIGN(0))
+               return 0;
+
+       return 1;
+}
+
+static struct ipt_match ipunusedbit_match
+= { { NULL, NULL }, "ipunusedbit", &match, &checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+       printk("ipt_ipunusedbit match loading\n");
+       return ipt_register_match(&ipunusedbit_match);
+}
+
+static void __exit fini(void)
+{
+       ipt_unregister_match(&ipunusedbit_match);
+       printk("ipt_ipunusedbit match unloaded\n");
+}
+
+module_init(init);
+module_exit(fini);
/* Shared library add-on to iptables for ipunusedbit. */
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <iptables.h>

/* Function which prints out usage message. */
static void
help(void)
{
	printf(
"ipunusedbit v%s takes no options\n"
"\n", NETFILTER_VERSION);
}

static struct option opts[] = {
	{0}
};

/* Initialize the match. */
static void
init(struct ipt_entry_match *m, unsigned int *nfcache)
{
	/* Can't cache this. */
	*nfcache |= NFC_UNKNOWN;
}

/* Function which parses command options; returns true if it
   ate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ipt_entry *entry,
      unsigned int *nfcache,
      struct ipt_entry_match **match)
{
	return 0;
}

/* Final check; must have specified --mac. */
static void final_check(unsigned int flags)
{
}

static
struct iptables_match ipunusedbit
= { NULL,
    "ipunusedbit",
    NETFILTER_VERSION,
    IPT_ALIGN(0),
    IPT_ALIGN(0),
    &help,
    &init,
    &parse,
    &final_check,
    NULL, /* print */
    NULL, /* save */
    opts
};

void _init(void)
{
	register_match(&ipunusedbit);
}

Reply via email to