Chapter 7: DB2: Discovery, Attack, and Defense

Finding DB2 on the Network

DB2 listens on a number of TCP ports. A default install of DB2 will have two instances, DB2-0 and DB2CTLSV-0, the former listening on TCP port 50000 and the latter on 50001. Finding DB2 on the network could be as simple as doing a TCP port scan looking for these ports. But there's no guarantee that the DB2 instances are actually listening on these ports. It could be that you'd need to scan and probe every port on every host on the network, but doing this takes too long and makes a considerable amount of "noise." There is a much better way of hunting for DB2 servers on the network. The Database Administration Server (DAS) listens on TCP and UDP port 523 and by sending a single packet to the broadcast address on UDP 523, every DB2 DAS should respond: a quick way of locating servers. The packet the client sends out simply contains

 DB2GETADDR\x00SQL08020 

The \x00 represents a NULL byte. The SQL08020 denotes the version of the client ”in this case 8.0.2. When the DB2 DAS receives this packet, whether sent directly to the host or to the broadcast address, it replies with its hostname and server version. The following code can be used to find DB2 servers on the network:

 #include <stdio.h> #include <windows.h> #include <winsock.h>     int QueryDB2Server(void); int StartWinsock(void);         struct sockaddr_in s_sa; struct hostent *he; unsigned int addr; int DB2Port=523; char host[260]=""; char request[]="DB2GETADDR\x00SQL08010";         int main(int argc, char *argv[]) {      unsigned int ErrorLevel=0;          if(argc != 2)      {           printf("\n\tQueryDB2\n\n");           printf("\tSends a UDP packet to port 523 to see if\n");           printf("\tthe remote server is running DB2.\n\n");           printf("\tUsage: C:\>%s target\n\n\t",argv[0]);           printf("David Litchfield\n\t(david@ngssoftware.com)\n\t6th September 2003\n\n");           return 0;      }      strncpy(host,argv[1],250);          if(StartWinsock() == 0)           return printf("Error starting Winsock.\n");            QueryDB2Server();      WSACleanup();                 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;      }          s_sa.sin_addr.s_addr=INADDR_ANY;      s_sa.sin_family=AF_INET;      s_sa.sin_port=htons((unsigned short)DB2Port);                 if (isalpha(host[0]))        {           he = gethostbyname(host);           if(he == NULL)           {                printf("Couldn't resolve %s\n",host);                WSACleanup();                return 0;           }           memcpy(&s_sa.sin_addr,he->h_addr,he->h_length);                 }      else      {           addr = inet_addr(host);           memcpy(&s_sa.sin_addr,&addr,4);      }            return 1; }             int QueryDB2Server(void) {      char resp[600]="";      int rcv=0,count=0;      SOCKET cli_sock;              cli_sock=socket(AF_INET,SOCK_DGRAM,0);      if(cli_sock==INVALID_SOCKET)      {           printf("socket error %d.\n",GetLastError());           return 0;      }                  if(connect(cli_sock,(LPSOCKADDR)&s_sa,sizeof(s_sa))==SOCKET_ERROR)      {           closesocket(cli_sock);           printf("Connect error %d.\n",GetLastError());           return 0;      }                 if(send(cli_sock, request, 20, 0) !=20)      {           closesocket(cli_sock);           printf("Send error %d\n",GetLastError());           return 0;      }      rcv = recv(cli_sock,resp,596,0);      if(rcv > 1)      {           while(count < rcv)           {                if(resp[count]==0x00)                     resp[count]=0x20;                count++;           }           printf("\n%s",resp);      }      else           printf("Server did not respond.\n");              return 0; } 
Note  

If you don't want your DB2 servers to respond to this, that is, make them more difficult to find on the network, you can do this by changing the mode of the Discovery setting. This should be done to help secure your DB2 installation. To "hide" the server, open the Control Center and right-click the instance in question. Select Configure Parameters from the menu. In the Keyword column, find Discover and select Disable.

Once a DB2 server has been found the DAS can be queried for various bits of information that are of use when seeking to break into it. The DAS supports something very like RPC to enable this ”but it's not RPC in the traditional sense. The DAS contains a number of functions that can be called remotely by a client. The client does this by simply sending the name of the function he wants to execute and passing any parameters along that may be required. The list of functions that can be called is restricted by the functions exported by .\dasfcn\db2dasfn.dll. Some of the functions require the client to be authenticated but others do not. For example, the db2dasGetDasLevel, getDasCfg, and getOSInfo functions can be called without the need to authenticate. With these functions it's possible to dump the exact version of the operating system, what databases are available and what ports they listen on, the DB2 install path ; pretty much anything one would need to write an exploit for a buffer overflow vulnerability without the need to guess address offsets and so on. The following code can be used to get the DB2 operating system information:

 #include <stdio.h> #include <windows.h> #include <winsock.h>     int DB2Port = 523; int MakeRequest(SOCKET, char *, int); int GetOSInfo(); int StartWinsock(void); SOCKET CreateSocket(); int ReceiveData(SOCKET s); int PrintResp(unsigned char *p, int l);     struct sockaddr_in s_sa; struct hostent *he; unsigned int addr; char host[260]="";     unsigned char c1[] =  "\x00\x00\x00\x00\x44\x42\x32\x44\x41\x53\x20\x20\x20\x20\x20\x20" "\x01\x03\x00\x00\x00\x10\x39\x7a\x00\x05\x03\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x02\x0d\x00\x00\x00";     unsigned char c2[] =  "\x00\x00\x00\x0d\x00\x00\x00\x0c\x00\x00\x00\x4a\x01";     unsigned char c3[] =  "\x00\x00\x00\x00\x44\x42\x32\x44\x41\x53\x20\x20\x20\x20\x20\x20" "\x01\x03\x00\x00\x00\x10\x39\x7a\x00\x05\x03\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x05\x2c\x00\x00\x00";     unsigned char c4[] =  "\x00\x00\x00\x2C\x00\x00\x00\x0c\x00\x00\x00\x08\x85\xe8\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";     unsigned char c5[] =  "\x00\x00\x00\x00\x44\x42\x32\x44\x41\x53\x20\x20\x20\x20\x20\x20" "\x01\x03\x00\x00\x00\x10\x39\x7a\x00\x05\x03\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x0a\x5d\x00\x00\x00";     unsigned char c6[] =  "\x00\x00\x00\x0d\x00\x00\x00\x0c\x00\x00\x00\x4a\x01\x00\x00\x00" "\x10\x00\x00\x00\x0c\x00\x00\x00\x4c\xff\xff\xff\xff\x00\x00\x00" "\x20\x00\x00\x00\x0c\x00\x00\x00\x04\x00\x00\x04\xb8\x64\x62\x32" "\x64\x61\x73\x4b\x6e\x6f\x77\x6e\x44\x73\x63\x76\x00\x00\x00\x00" "\x20\x00\x00\x00\x0c\x00\x00\x00\x04\x00\x00\x04\xb8\x64\x62\x32" "\x4b\x6e\x6f\x77\x6e\x44\x73\x63\x76\x53\x72\x76\x00";     unsigned char c7[] =  "\x00\x00\x00\x00\x44\x42\x32\x44\x41\x53\x20\x20\x20\x20\x20\x20" "\x01\x03\x00\x00\x00\x10\x39\x7a\x00\x05\x03\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x06\xac\x00\x00\x00";     unsigned char c8[] =  "\x00\x00\x00\x0d\x00\x00\x00\x0c\x00\x00\x00\x4a\x01\x00\x00\x00" "\x20\x00\x00\x00\x0c\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x03" "\x9c\x00\x00\x00\x00\x41\x17\x8e\x48\xc0\xa8\x00\x21\x00\x00\x00" "\x10\x00\x00\x00\x0c\x00\x00\x00\x4c\xff\xff\xff\xff\x00\x00\x00" "\x10\x00\x00\x00\x0c\x00\x00\x00\x4c\xff\xff\xff\xff\x00\x00\x00" "\x19\x00\x00\x00\x0c\x00\x00\x00\x04\x00\x00\x04\xb8\x64\x62\x32" "\x64\x61\x73\x66\x6e\x00\x00\x00\x00\x1a\x00\x00\x00\x0c\x00\x00" "\x00\x04\x00\x00\x04\xb8\x67\x65\x74\x4f\x53\x49\x6e\x66\x6f\x00" "\x00\x00\x00\x0c\x00\x00\x00\x0c\x00\x00\x00\x04\x00\x00\x00\x10" "\x00\x00\x00\x0c\x00\x00\x00\x4c\xff\xff\xff\xff\x00\x00\x00\x10" "\x00\x00\x00\x0c\x00\x00\x00\x4c\xff\xff\xff\xff\x00\x00\x00\x00" "\x44\x42\x32\x44\x41\x53\x20\x20\x20\x20\x20\x20\x01\x03\x00\x00" "\x00\x10\x39\x7a\x00\x05\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x07\xaf\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00\x0c\x00\x00\x00" "\x04\x00\x00\x04\xb8\x67\x65\x74\x4f\x53\x49\x6e\x66\x6f\x00\x00" "\x00\x00\x19\x00\x00\x00\x0c\x00\x00\x00\x04\x00\x00\x04\xb8\x64" "\x62\x32\x64\x61\x73\x66\x6e\x00\x00\x00\x00\x10\x00\x00\x00\x0c" "\x00\x00\x00\x4c\x00\x7a\x39\x10\x00\x00\x00\x10\x00\x00\x00\x0c" "\x00\x00\x00\x4c\x00\x00\x00\x03\x00\x00\x00\x10\x00\x00\x00\x0c" "\x00\x00\x00\x4c\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x0c" "\x00\x00\x00\x08\x00\x00\x00\x10\x00\x00\x00\x0c\x00\x00\x00\x4c" "\x00\x00\x00\x03\x00\x00\x00\x30\x00\x00\x00\x0c\x00\x00\x00\x08" "\x00\x00\x00\x0c\x00\x00\x00\x0c\x00\x00\x00\x18\x00\x00\x00\x0c" "\x00\x00\x00\x0c\x00\x00\x00\x18\x00\x00\x00\x0c\x00\x00\x00\x0c" "\x00\x00\x00\x18";     int main(int argc, char *argv[]) {      unsigned int ErrorLevel=0;      int count = 0;      char buffer[100000]="";      if(argc != 2)      {           printf("\n\tGetOSInfo for DB2\n\n");           printf("\tUsage: C:\>%s target\n\n",argv[0]);           printf("\tDavid Litchfield\n\tdavid@ngssoftware.com\n");           printf("\t10 September 2004\n");           return 0;      }      strncpy(host,argv[1],250);      if(StartWinsock()==0)           return printf("Error starting Winsock.\n");           GetOsInfo();      WSACleanup();      return 0;     }               int GetOsInfo() {      SOCKET s = NULL;          s = CreateSocket();      if(s==INVALID_SOCKET)           return 0;          MakeRequest(s,c1,sizeof(c1)-1);      _sleep(250);      MakeRequest(s,c2,sizeof(c2)-1);      ReceiveData(s);      ReceiveData(s);      MakeRequest(s,c3,sizeof(c3)-1);      _sleep(250);      MakeRequest(s,c4,sizeof(c4)-1);      ReceiveData(s);      ReceiveData(s);      MakeRequest(s,c5,sizeof(c5)-1);      _sleep(250);      MakeRequest(s,c6,sizeof(c6)-1);      ReceiveData(s);      ReceiveData(s);      MakeRequest(s,c7,sizeof(c7)-1);      _sleep(250);      MakeRequest(s,c8,sizeof(c8)-1);      ReceiveData(s);      ReceiveData(s);              closesocket(s);      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;      }          s_sa.sin_addr.s_addr=INADDR_ANY;      s_sa.sin_family=AF_INET;      s_sa.sin_port=htons((unsigned short)DB2Port);                 if (isalpha(host[0]))        {           he = gethostbyname(host);           if(he == NULL)           {                printf("Couldn't resolve %s\n",host);                WSACleanup();                return 0;           }           memcpy(&s_sa.sin_addr,he->h_addr,he->h_length);                 }      else      {           addr = inet_addr(host);           memcpy(&s_sa.sin_addr,&addr,4);      }            return 1; }             SOCKET CreateSocket() {      SOCKET cli_sock;      unsigned int ttlbytes=0;      unsigned int to=10;      struct sockaddr_in cli_addr;          cli_sock=socket(AF_INET,SOCK_STREAM,0);      if (cli_sock==INVALID_SOCKET)           return printf("socket error.\n");          setsockopt(cli_sock,SOL_SOCKET,SO_RCVTIMEO,(char *)&to,sizeof(unsigned int));              s_sa.sin_port=htons((unsigned short)DB2Port);          if (connect(cli_sock,(LPSOCKADDR)&s_sa,sizeof(s_sa))==SOCKET_ERROR)      {           closesocket(cli_sock);           printf("Connect error.\n");           ExitProcess(0);      }      return cli_sock; }     int MakeRequest(SOCKET s, char *req, int x) {      int snd=0;           snd=send(s, req , x , 0);      return 0; }     int ReceiveData(SOCKET s) {      unsigned char resp[6000]="";      int rcv=0;               rcv=recv(s, resp , 5996 , 0);      if(rcv == SOCKET_ERROR)      {           printf("ERROR\n");           return 0;      }      PrintResp(resp,rcv);      printf("\n\n\n");      return 0; }     int PrintResp(unsigned char *p, int l) {      int c = 0;      int d = 0;      while(c < l)      {           printf("%.2X ",p[c]);           c ++;           if(c % 16 == 0)           {                d = c - 16;                printf("\t");                while(d < c)                {                          if(p[d] == 0x0A  p[d] == 0x0D)                          printf(" ");                     else                          printf("%c",p[d]);                     d++;                }                printf("\n");                d = 0;           }      }      d = c - 16;      printf("\t");      while(d < c)      {                if(p[d] == 0x0A  p[d] == 0x0D)                printf(" ");           else                printf("%c",p[d]);           d++;      }      printf("\n");      d = 0;                return 0; } 


Database Hacker's Handbook. Defending Database Servers
The Database Hackers Handbook: Defending Database Servers
ISBN: 0764578014
EAN: 2147483647
Year: 2003
Pages: 156

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