* Idea: string replace
@ 2002-10-01 1:13 Peter Surda
2002-10-01 7:27 ` Patrick Schaaf
0 siblings, 1 reply; 5+ messages in thread
From: Peter Surda @ 2002-10-01 1:13 UTC (permalink / raw)
To: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 1222 bytes --]
Hello!
I have an idea, which is IMHO very suitable for China. Er, no, wanted to say
something different, suitable for me. How about adding a --replace-with option
to the string match? Is it difficult? Or could this be done with the NETLINK
target?
Why am I asking? I would like to prevent users behind a router becoming
infected with a virus (a specific one, not the thousands others). I made a
string match for it and direct all pop3/imap trafic through this rule. The
problem is, although I can find it, I can't reasonably get rid of it. The
most reasonable solution seems to be to -j REJECT --reject-with tcp-reset, but
I assume this causes problems. So I'd rather change the string to something
bogus, which will make the virus unexecutable.
Or do you know a filtering transparent pop3/imap proxy? I have no access to
the dozens of servers the users have emails on. Unless the solution is fully
transparent, it will cause too high organisational overhead which is not
sensible to manage for us. Also not manageable is educating the users about
"safe use of computers".
Bye,
Peter Surda (Shurdeek) <shurdeek@panorama.sth.ac.at>, ICQ 10236103, +436505122023
--
Disc space - The final frontier.
[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Idea: string replace
2002-10-01 1:13 Idea: string replace Peter Surda
@ 2002-10-01 7:27 ` Patrick Schaaf
2002-10-01 21:06 ` Peter Surda
0 siblings, 1 reply; 5+ messages in thread
From: Patrick Schaaf @ 2002-10-01 7:27 UTC (permalink / raw)
To: Peter Surda; +Cc: netfilter-devel
Hi Peter,
> I have an idea, which is IMHO very suitable for China. Er, no, wanted to say
> something different, suitable for me. How about adding a --replace-with option
> to the string match? Is it difficult?
I assume that you are aware of the reasons why the STRING approach
risks both false positives and false negatives, and I'll spare you
the usual rant.
Regarding the "is it difficult" question, that depends on whether you
want to replace with a string of identical length (piece of cake),
or a string of different length. In the latter case, your new code
has to reallocate the packet buffer to the appropriate new total
size, and it must recalculate TCP sequence numbers (both ways,
permanently, meaning you absolutely need connection tracking).
To get a feel for the complexity, have a look at the FTP connection
tracking and NAT helpers - they are doing just that with the FTP
PORT command in the control connection, when NAT is active.
If you actually venture to implement this, please really look at
what the FTP helpers do, and think hard about how to factor out
the complexity into a generic helper module that can be used both
from the FTP code, and from your new code.
good luck!
Patrick
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Idea: string replace
2002-10-01 7:27 ` Patrick Schaaf
@ 2002-10-01 21:06 ` Peter Surda
2002-10-01 23:33 ` Peter Surda
0 siblings, 1 reply; 5+ messages in thread
From: Peter Surda @ 2002-10-01 21:06 UTC (permalink / raw)
To: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 1543 bytes --]
On Tue, Oct 01, 2002 at 09:27:02AM +0200, Patrick Schaaf wrote:
> Hi Peter,
Hi.
> > I have an idea, which is IMHO very suitable for China. Er, no, wanted to say
> > something different, suitable for me. How about adding a --replace-with option
> > to the string match? Is it difficult?
> I assume that you are aware of the reasons why the STRING approach
> risks both false positives and false negatives, and I'll spare you
> the usual rant.
I understand that both cases can occur, and for what I need it I accept this.
> Regarding the "is it difficult" question, that depends on whether you
> want to replace with a string of identical length (piece of cake),
Actually, I didn't think so far as to use different lengths, somehow I
subconsiously assumed it is far from easy. Again, I only need this for a very
specific purpose (disabling one virus), for which IMHO same-length-replace is
sufficient.
So, I took a look at the source, and I assume this is indeed trivial,
something like
char *temp;
if ((temp = search (blahblah)) != NULL) {
if (info->replace != NULL)
memcpy (temp, info->replace, min (match_length, replace_length));
return 1 ^ info->invert;
} else
return 0 ^ info->invert;
The more difficult thing seems to be the stuff around (userspace integration).
> good luck!
Oh I doubt I am good enough to write different-length-replace function :-)
> Patrick
Bye,
Peter Surda (Shurdeek) <shurdeek@panorama.sth.ac.at>, ICQ 10236103, +436505122023
--
Failure is not an option. It comes bundled with your Microsoft product.
[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Idea: string replace
2002-10-01 21:06 ` Peter Surda
@ 2002-10-01 23:33 ` Peter Surda
2002-10-02 13:44 ` Gianni Tedesco
0 siblings, 1 reply; 5+ messages in thread
From: Peter Surda @ 2002-10-01 23:33 UTC (permalink / raw)
To: netfilter-devel; +Cc: Gianni Tedesco
[-- Attachment #1.1: Type: text/plain, Size: 1187 bytes --]
On Tue, Oct 01, 2002 at 11:06:50PM +0200, Peter Surda wrote:
> > Regarding the "is it difficult" question, that depends on whether you
> > want to replace with a string of identical length (piece of cake),
> Actually, I didn't think so far as to use different lengths, somehow I
> subconsiously assumed it is far from easy. Again, I only need this for a very
> specific purpose (disabling one virus), for which IMHO same-length-replace is
> sufficient.
Ok, so I tried, I tried really hard <g>, and it compiled, and it didn't crash,
and it seems to behave as expected (the virus attachment arrives or is
downloaded, but is artifically corrupt and doesn't work). Attached patches
(one userspace and one kernel) against cvs from end of July.
The string match has a new option, --replace-with, that takes one string as a
value. I think the code is straightforward, the checksumming stuff is pasted
from nat_helper.c (but it doesn't do conntrack of course).
Please test and report :-). I am sure there are more cool ways to use it than
fighting virii.
Bye,
Peter Surda (Shurdeek) <shurdeek@panorama.sth.ac.at>, ICQ 10236103, +436505122023
--
rm -f /bin/laden
[-- Attachment #1.2: iptables-string.patch --]
[-- Type: text/plain, Size: 2335 bytes --]
--- extensions/libipt_string.c Wed May 29 15:08:16 2002
+++ ../userspace/extensions/libipt_string.c Wed Oct 2 00:31:43 2002
@@ -23,7 +23,8 @@
{
printf(
"STRING match v%s options:\n"
-"--string [!] string Match a string in a packet\n",
+"--string [!] string Match a string in a packet\n"
+"--replace-with replace Replace with replace\n",
IPTABLES_VERSION);
fputc('\n', stdout);
@@ -31,6 +32,7 @@
static struct option opts[] = {
{ "string", 1, 0, '1' },
+ { "replace-with", 1, 0, '2' },
{0}
};
@@ -48,6 +50,13 @@
else exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s);
}
+static void
+parse_replace(const unsigned char *s, struct ipt_string_info *info)
+{
+ if (strlen(s) <= BM_MAX_NLEN) strcpy(info->replace, s);
+ else exit_error(PARAMETER_PROBLEM, "Replace STRING too long `%s'", s);
+}
+
/* Function which parses command options; returns true if it
ate an option */
static int
@@ -67,6 +76,10 @@
stringinfo->len=strlen((char *)&stringinfo->string);
*flags = 1;
break;
+ case '2':
+ parse_replace(argv[optind-1], stringinfo);
+ stringinfo->replace_len=strlen((char *)&stringinfo->replace);
+ break;
default:
return 0;
@@ -83,6 +96,12 @@
printf("%s ",string);
}
+static void
+print_replace(char replace[], int numeric)
+{
+ printf("%s ",replace);
+}
+
/* Final check; must have specified --string. */
static void
final_check(unsigned int flags)
@@ -101,6 +120,11 @@
printf("STRING match ");
print_string(((struct ipt_string_info *)match->data)->string,
((struct ipt_string_info *)match->data)->invert, numeric);
+ if (((struct ipt_string_info *)match->data)->replace_len > 0) {
+ printf(" replace-with ");
+ print_replace(((struct ipt_string_info *)match->data)->replace,
+ numeric);
+ }
}
/* Saves the union ipt_matchinfo in parsable form to stdout. */
@@ -110,6 +134,11 @@
printf("--string ");
print_string(((struct ipt_string_info *)match->data)->string,
((struct ipt_string_info *)match->data)->invert, 0);
+ if (((struct ipt_string_info *)match->data)->replace_len > 0) {
+ printf(" --replace-with ");
+ print_replace(((struct ipt_string_info *)match->data)->replace,
+ 0);
+ }
}
static
[-- Attachment #1.3: replace-kernel.patch --]
[-- Type: text/plain, Size: 2331 bytes --]
diff -ur linux-2.4.19-rc3-ac3-mppe-netfilter-htb-noreplace/include/linux/netfilter_ipv4/ipt_string.h linux-2.4.19-rc3-ac3-mppe-netfilter-htb/include/linux/netfilter_ipv4/ipt_string.h
--- linux-2.4.19-rc3-ac3-mppe-netfilter-htb-noreplace/include/linux/netfilter_ipv4/ipt_string.h Tue Oct 1 02:20:32 2002
+++ linux-2.4.19-rc3-ac3-mppe-netfilter-htb/include/linux/netfilter_ipv4/ipt_string.h Tue Oct 1 23:44:00 2002
@@ -14,8 +14,10 @@
struct ipt_string_info {
char string[BM_MAX_NLEN];
+ char replace[BM_MAX_NLEN];
u_int16_t invert;
u_int16_t len;
+ u_int16_t replace_len;
};
#endif /* _IPT_STRING_H */
diff -ur linux-2.4.19-rc3-ac3-mppe-netfilter-htb-noreplace/net/ipv4/netfilter/ipt_string.c linux-2.4.19-rc3-ac3-mppe-netfilter-htb/net/ipv4/netfilter/ipt_string.c
--- linux-2.4.19-rc3-ac3-mppe-netfilter-htb-noreplace/net/ipv4/netfilter/ipt_string.c Thu Jul 25 20:38:15 2002
+++ linux-2.4.19-rc3-ac3-mppe-netfilter-htb/net/ipv4/netfilter/ipt_string.c Wed Oct 2 01:01:50 2002
@@ -21,7 +21,10 @@
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/file.h>
+#include <linux/ip.h>
#include <net/sock.h>
+#include <net/checksum.h>
+#include <net/tcp.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_string.h>
@@ -110,7 +113,7 @@
const struct ipt_string_info *info = matchinfo;
struct iphdr *ip = skb->nh.iph;
int hlen, nlen;
- char *needle, *haystack;
+ char *needle, *haystack, *result;
proc_ipt_search search=search_linear;
if ( !ip ) return 0;
@@ -137,7 +140,22 @@
}
}
- return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
+ if ((result = search(needle, haystack, nlen, hlen)) != NULL &&
+ info->replace_len > 0) {
+ struct tcphdr *tcph = (void *)ip + ip->ihl*4;
+ u_int32_t tcplen = skb->len - ip->ihl*4;
+ u_int32_t datalen = tcplen - tcph->doff*4;
+
+ memcpy (result, info->replace, min (info->len, info->replace_len));
+
+ skb->csum = csum_partial((char *)tcph + tcph->doff*4, datalen, 0);
+ tcph->check = 0;
+ tcph->check = tcp_v4_check(tcph, tcplen, ip->saddr, ip->daddr,
+ csum_partial((char *)tcph, tcph->doff*4, skb->csum));
+ ip_send_check(ip);
+ }
+
+ return ((result != NULL) ^ info->invert);
}
static int
[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Idea: string replace
2002-10-01 23:33 ` Peter Surda
@ 2002-10-02 13:44 ` Gianni Tedesco
0 siblings, 0 replies; 5+ messages in thread
From: Gianni Tedesco @ 2002-10-02 13:44 UTC (permalink / raw)
To: Peter Surda; +Cc: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 2090 bytes --]
On Wed, 2002-10-02 at 00:33, Peter Surda wrote:
> On Tue, Oct 01, 2002 at 11:06:50PM +0200, Peter Surda wrote:
> > > Regarding the "is it difficult" question, that depends on whether you
> > > want to replace with a string of identical length (piece of cake),
> > Actually, I didn't think so far as to use different lengths, somehow I
> > subconsiously assumed it is far from easy. Again, I only need this for a very
> > specific purpose (disabling one virus), for which IMHO same-length-replace is
> > sufficient.
> Ok, so I tried, I tried really hard <g>, and it compiled, and it didn't crash,
> and it seems to behave as expected (the virus attachment arrives or is
> downloaded, but is artifically corrupt and doesn't work). Attached patches
> (one userspace and one kernel) against cvs from end of July.
>
> The string match has a new option, --replace-with, that takes one string as a
> value. I think the code is straightforward, the checksumming stuff is pasted
> from nat_helper.c (but it doesn't do conntrack of course).
Cool, I'm pretty sure you could pre-compute the checksum differences in
userspace and pass them in the info struct that would save dirtying lots
of CPU caches *too* much. :]
> Please test and report :-). I am sure there are more cool ways to use it than
> fighting virii.
Everyone here knows the problem of this approach for virus killing. To
do it right you need to wory about if the virus straddles two packets,
is radix 64 encoded, is using HTTP gzip ecoding, is using SMTP TLS,
never mind the various ptacek/newsham style attacks for TCP etc etc...
That said, I'm sure this will catch 99% of all viruses because they
probably wont straddle two packets, they certainly aren't deliberatly
evasive and they are usually sent via mail APIs which allow little
control that would let you do most of the interesting evasion
techniques.
--
// Gianni Tedesco (gianni at ecsc dot co dot uk)
lynx --source www.scaramanga.co.uk/gianni-at-ecsc.asc | gpg --import
8646BE7D: 6D9F 2287 870E A2C9 8F60 3A3C 91B5 7669 8646 BE7D
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 232 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2002-10-02 13:44 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-10-01 1:13 Idea: string replace Peter Surda
2002-10-01 7:27 ` Patrick Schaaf
2002-10-01 21:06 ` Peter Surda
2002-10-01 23:33 ` Peter Surda
2002-10-02 13:44 ` Gianni Tedesco
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.