安全研究
安全漏洞
Netfilter跟踪连接远程拒绝服务攻击漏洞
发布日期:2003-08-02
更新日期:2003-08-06
受影响系统:
Linux kernel 2.4.20描述:
- Mandrake Linux 9.1
- RedHat Linux 9.0
- Slackware Linux 9.0
BUGTRAQ ID: 8331
CVE(CAN) ID: CVE-2003-0187
Netfilter是一款Linux Kernel下的防火墙构架实现。
Netfilter在处理连接跟踪机制时存在问题,远程攻击者可以利用这个漏洞对使用连接跟踪模块的系统进行拒绝服务攻击。
2.4.20内核介绍了一个新的改变,是对一般连接列表支持。连接跟踪的核心是依据以前的识别'UNCONFIRMED'连接的行为。'UNCONFIRMED'也就是说我们只能看到一个方向的连接,由于连接跟踪不能识别连接是否正确,所以它们被分配了一个很高的超时值。
Netfilter发布了一个补丁使连接跟踪器不再依靠Linux连接列表API的任何特定行为。
<*来源:Netfilter Core Team (coreteam@netfilter.org)
链接:http://marc.theaimsgroup.com/?l=bugtraq&m=105986028426824&w=2
*>
建议:
厂商补丁:
Linux
-----
采用如下补丁:
diff -urN --exclude-from=diff.exclude linux-2.4.20-base/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.20-del/include/linux/netfilter_ipv4/ip_conntrack.h
--- linux-2.4.20-base/include/linux/netfilter_ipv4/ip_conntrack.h Fri Nov 29 00:53:15 2002
+++ linux-2.4.20-del/include/linux/netfilter_ipv4/ip_conntrack.h Fri Feb 21 17:01:38 2003
-6,6 +6,7
#include <linux/config.h>
#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
+#include <linux/bitops.h>
#include <asm/atomic.h>
enum ip_conntrack_info
-41,6 +42,10
/* Conntrack should never be early-expired. */
IPS_ASSURED_BIT = 2,
IPS_ASSURED = (1 << IPS_ASSURED_BIT),
+
+ /* Connection is confirmed: originating packet has left box */
+ IPS_CONFIRMED_BIT = 3,
+ IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
};
#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
-159,7 +164,7
struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
/* Have we seen traffic both ways yet? (bitset) */
- volatile unsigned long status;
+ unsigned long status;
/* Timer function; drops refcnt when it goes off. */
struct timer_list timeout;
-254,7 +259,7
/* It's confirmed if it is, or has been in the hash table. */
static inline int is_confirmed(struct ip_conntrack *ct)
{
- return ct->tuplehash[IP_CT_DIR_ORIGINAL].list.next != NULL;
+ return test_bit(IPS_CONFIRMED_BIT, &ct->status);
}
extern unsigned int ip_conntrack_htable_size;
diff -urN --exclude-from=diff.exclude linux-2.4.20-base/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.20-del/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.4.20-base/net/ipv4/netfilter/ip_conntrack_core.c Tue Feb 18 17:08:21 2003
+++ linux-2.4.20-del/net/ipv4/netfilter/ip_conntrack_core.c Fri Feb 21 17:01:39 2003
-292,9 +292,6
{
DEBUGP("clean_from_lists(%p)\n", ct);
MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
- /* Remove from both hash lists: must not NULL out next ptrs,
- otherwise we'll look unconfirmed. Fortunately, LIST_DELETE
- doesn't do this. --RR */
LIST_DELETE(&ip_conntrack_hash
[hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)],
&ct->tuplehash[IP_CT_DIR_ORIGINAL]);
-467,6 +464,7
ct->timeout.expires += jiffies;
add_timer(&ct->timeout);
atomic_inc(&ct->ct_general.use);
+ set_bit(IPS_CONFIRMED_BIT, &ct->status);
WRITE_UNLOCK(&ip_conntrack_lock);
return NF_ACCEPT;
}
-585,7 +583,7
connection. Too bad: we're in trouble anyway. */
static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
{
- return !(i->ctrack->status & IPS_ASSURED);
+ return !(test_bit(IPS_ASSURED_BIT, &i->ctrack->status));
}
static int early_drop(struct list_head *chain)
-720,7 +718,7
conntrack, expected);
/* Welcome, Mr. Bond. We've been expecting you... */
IP_NF_ASSERT(master_ct(conntrack));
- conntrack->status = IPS_EXPECTED;
+ __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
conntrack->master = expected;
expected->sibling = conntrack;
LIST_DELETE(&ip_conntrack_expect_list, expected);
-768,11 +766,11
*set_reply = 1;
} else {
/* Once we've had two way comms, always ESTABLISHED. */
- if (h->ctrack->status & IPS_SEEN_REPLY) {
+ if (test_bit(IPS_SEEN_REPLY_BIT, &h->ctrack->status)) {
DEBUGP("ip_conntrack_in: normal packet for %p\n",
h->ctrack);
*ctinfo = IP_CT_ESTABLISHED;
- } else if (h->ctrack->status & IPS_EXPECTED) {
+ } else if (test_bit(IPS_EXPECTED_BIT, &h->ctrack->status)) {
DEBUGP("ip_conntrack_in: related packet for %p\n",
h->ctrack);
*ctinfo = IP_CT_RELATED;
diff -urN --exclude-from=diff.exclude linux-2.4.20-base/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.4.20-del/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
--- linux-2.4.20-base/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Tue Feb 18 17:07:26 2003
+++ linux-2.4.20-del/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Fri Feb 21 17:03:35 2003
-192,7 +192,7
have an established connection: this is a fairly common
problem case, so we can delete the conntrack
immediately. --RR */
- if (!(conntrack->status & IPS_SEEN_REPLY) && tcph->rst) {
+ if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) && tcph->rst) {
WRITE_UNLOCK(&tcp_lock);
if (del_timer(&conntrack->timeout))
conntrack->timeout.function((unsigned long)conntrack);
diff -urN --exclude-from=diff.exclude linux-2.4.20-base/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux-2.4.20-del/net/ipv4/netfilter/ip_conntrack_proto_udp.c
--- linux-2.4.20-base/net/ipv4/netfilter/ip_conntrack_proto_udp.c Fri Nov 29 00:53:15 2002
+++ linux-2.4.20-del/net/ipv4/netfilter/ip_conntrack_proto_udp.c Fri Feb 21 17:01:39 2003
-51,7 +51,7
{
/* If we've seen traffic both ways, this is some kind of UDP
stream. Extend timeout. */
- if (conntrack->status & IPS_SEEN_REPLY) {
+ if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
ip_ct_refresh(conntrack, UDP_STREAM_TIMEOUT);
/* Also, more likely to be important, and not a probe */
set_bit(IPS_ASSURED_BIT, &conntrack->status);
diff -urN --exclude-from=diff.exclude linux-2.4.20-base/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.20-del/net/ipv4/netfilter/ip_conntrack_standalone.c
--- linux-2.4.20-base/net/ipv4/netfilter/ip_conntrack_standalone.c Fri Nov 29 00:53:15 2002
+++ linux-2.4.20-del/net/ipv4/netfilter/ip_conntrack_standalone.c Fri Feb 21 21:10:37 2003
-77,7 +77,7
}
static unsigned int
-print_conntrack(char *buffer, const struct ip_conntrack *conntrack)
+print_conntrack(char *buffer, struct ip_conntrack *conntrack)
{
unsigned int len;
struct ip_conntrack_protocol *proto
-95,12 +95,12
len += print_tuple(buffer + len,
&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
proto);
- if (!(conntrack->status & IPS_SEEN_REPLY))
+ if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
len += sprintf(buffer + len, "[UNREPLIED] ");
len += print_tuple(buffer + len,
&conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
proto);
- if (conntrack->status & IPS_ASSURED)
+ if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
len += sprintf(buffer + len, "[ASSURED] ");
len += sprintf(buffer + len, "use=%u ",
atomic_read(&conntrack->ct_general.use));
--
浏览次数:3642
严重程度:0(网友投票)
绿盟科技给您安全的保障