1、实验目的 1.了解 SQL 注入的基本原理2.掌握 PHP 脚本访问 MySQL 数据库的基本方法3.掌握程序设计中避免出现 SQL 注入漏洞的基本方法学时分配 2 学时实验人数 每组 1 人系统环境 Linux网络环境 交换网络结构实验工具 MySQL 数据库PHP 脚本语言实验类型 综合型实验原理 一SQL 注入攻击1什么是 SQL 注入攻击所谓 SQL 注入式攻击,就是攻击者把 SQL 命令插入到 Web 表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的 SQL 命令。2为何会有 SQL 注入攻击很多电子商务应用程序都使用数据库来存储信息。不论是产品信息,账目信息还是其它类型的数
2、据,数据库都是 Web 应用环境中非常重要的环节。SQL 命令就是前端 Web和后端数据库之间的接口,使得数据可以传递到 Web 应用程序,也可以从其中发送出来。需要对这些数据进行控制,保证用户只能得到授权给他的信息。可是,很多 Web 站点都会利用用户输入的参数动态的生成 SQL 查询要求,攻击者通过在 URL、表格域,或者其他的输入域中输入自己的 SQL 命令,以此改变查询属性,骗过应用程序,从而可以对数据库进行不受限的访问。因为 SQL 查询经常用来进行验证、授权、订购、打印清单等,所以,允许攻击者任意提交 SQL 查询请求是非常危险的。通常,攻击者可以不经过授权,使用 SQL 输入从数
3、据库中获取信息。3何时使用 SQL 注入攻击当 Web 应用向后端的数据库提交输入时,就可能遭到 SQL 注入攻击。可以将 SQL 命令人为的输入到 URL、表格域,或者其他一些动态生成的 SQL 查询语句的输入参数中,完成上述攻击。因为大多数的 Web 应用程序都依赖于数据库的海量存储和相互间的逻辑关系(用户权限许可,设置等),所以,每次的查询中都会存在大量的参数。二MySQL 简介SQL 是结构化查询语言的简称,它是全球通用的标准数据库查询语言,主要用于关系型数据的操作和管理,如增加记录,删除记录,更改记录,查询记录等,常用命令知识如表 15-1-1 所示。表 15-1-1 SQL 常用命
4、令命令短语 功能 例句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 (修改 A 表中 i=1的 i 值为 2)insert 用于添加记录insert into A values(1, 2,3) (向 A 表中插入一条记录(i,j,k)对应为 (1, 2,3)delete 用于删除记录delete A where i=2 (删除 A 标中 i=2 的所有表项)
5、from用于指定操作的对象名(表,视图,数据库等的名称)见 selectwhere用于指定查询条件select *from A,B where A.name=B.name and A.id=B.idand 逻辑与 1=1 and 22not 逻辑非 not 11= 相等关系或赋值 见 and、or 、not,=,” )包含。与客户端的 JavaScript 不同的是,PHP 代码是运行在服务端的。在服务器上建立了如上例类似的代码,则在运行该脚本后,客户端就能接收到其处理结果,但他们无法得知其背后的代码是如何动作的。2PHP 能做什么PHP 主要是用于服务端的脚本程序,因此可以用 PHP 来完成
6、任何其它的 CGI 程序能够完成的工作,例如收集表单数据,生成动态网页,或者发送/接收 Cookies。但 PHP 的功能远不局限于此。PHP 脚本主要用于以下三个领域。(1)服务端脚本这是 PHP 最传统,也是最主要的目标领域。开展这项工作需要具备以下三点:PHP解析器(CGI 或者服务器模块) 、Web 服务器和 Web 浏览器。(2)命令行脚本可以编写一段 PHP 脚本,并且不需要任何服务器或者浏览器来运行它。通过这种方式,仅仅只需要 PHP 解析器来执行。(3)编写客户端的 GUI 应用程序对于图形界面的应用程序来说,PHP 或许不是一种最好的语言,但是如果非常精通PHP,并且希望在客
7、户端应用程序中使用 PHP 的一些高级特性,则可以利用 PHP-GTK 来编写这些程序。PHP 能够用在所有的主流操作系统上,包括 Linux、Unix、Microsoft Windows、Mac OS X 等。并且 PHP 已经支持了大多数的 Web 服务器,包括 Apache、IIS、PWS、Netscape等。五使用 PHP 从 Web 访问 MySQL 数据库1Web 数据库架构的工作原理以下给出的是 Web 数据库架构的基本步骤:(1)客户 Web 浏览器发出一个 HTTP 请求,请求特定的 Web 页面。例如,客户使用一个 HTML 表单请求搜索 Book 数据库中所有于 2008
8、 年出版的书籍。该搜索结果页面为results.php。(2)Web 服务器接收到对 results.php 页面的请求后,检索该文件,并将其传递给PHP 引擎处理。(3)PHP 引擎开始解析脚本。脚本主要包括了连接到数据库和执行查询的命令(执行对书籍的搜索) 。PHP 启动了对 MySQL 服务器的连接并向该服务器发送适当的查询。(4)MySQL 服务器接收到数据库查询的请求,开始处理这个查询,并将查询结果书籍列表返回给 PHP 引擎。(5)PHP 引擎完成了脚本的运行后(其中包括以 HTML 格式表示经过处理后的查询结果) ,然后将该 HTML 返回给 Web 服务器。(6)Web 服务器
9、再将 HTML 返回给客户端浏览器,用户就可以看到所要求查询的书籍。2从 Web 查询数据库的基本步骤在任何用于从 Web 访问数据库的脚本中,都应该遵循以下这些基本步骤:(1)检查并过滤来自用户的数据。(2)建立一个到数据库的连接。(3)查询数据库。(4)获取查询结果。(5)将结果显示给用户。3PHP 访问 Mysql 数据库(1)连接到 MySQL 服务器在从目标数据库中获取 Web 页面所包含的内容之前,首先必须知道如何建立与MySQL 的连接。通常情况下,使用 MySQL 客户端程序来实现连接数据库,但 PHP 不需要这样的程序,对连接 MySQL 的支持是语言内置的。下面的函数用来建
10、立与 MySQL 数据库的连接。 address 是 MySQL 服务器(MySQL 服务软件所在计算机)的 IP 地址或主机名(如果与 Web 服务器所在是同一台主机,可以使用“localhost” ) ; username、password 是用来连接 MySQL 服务器的用户名及口令; 执行成功返回 MySQL 连接标识(link id) ,否则返回 FALSE。(2)选择工作数据库在 PHP 与 MySQL 成功建立连接后,可以使用如下函数选择工作数据库 dbname 是欲选择的工作数据库名称; link id 是连接标识,此参数为可选参数,如果没有指定连接标识,则使用上一个打开的连接
11、; 执行成功返回 TRUE,否则返回 FALSE。(3)执行 SQL 查询通过下面的函数可以向指定的连接标识关联的服务器中的当前工作数据库发送一条查询(SQL 语句) 。sql 为查询字符串,并且不应以分号结束; 如果没有指定 link id,则使用上一个打开的连接; 此函数仅对 SELECT、SHOW、EXPLAIN 或 DESCRIBE 语句返回一个资源标识,如果查询执行不正确则返回 FALSE。对于其它类型的 SQL 语句,执行成功时返回 TRUE,否则返回 FALSE。(4)发送一条 MySQL 查询(PHP4.0.6 起不提供使用此函数) 根据查询结果返回一个正的 MySQL 结果资
12、源号,出错时返回 FALSE。(5)获取前一次 MySQL 操作所影响的记录行数 此函数返回最后一次与连接标识关联的 INSERT、UPDATE 或 DELETE 查询所影响的记录行数。如果连接标识没有指定,则默认使用最后一次由 mysql_connect()函数打开的连接标识。(6)获取结果集中行的数目 此函数仅对 SELECT 语句有效。要取得被 INSERT、UPDATE 或者 DELETE 查询所影响到的行的数目,用 mysql_affected_row()。(7)从结果集中获取一行作为关联数组 返回根据从结果集获取的行生成的数组,如果没有更多行则返回 FALSE。(8)取得上一步 I
13、NSERT 操作产生的 ID 返回给定的 link id 中上一步 INSERT 查询中产生的 AUTO_INCREMENT 的 ID 号。如果没有指定 link id,则使用上一个打开的连接。(9)关闭 MySQL 连接 关闭指定的连接标识所关联到的到 MySQL 服务器的连接。如果没有指定 link id,则关闭上一个打开的连接。通常不需要使用此函数,因为已打开的非持久连接会在脚本执行完毕后自动关闭。实验步骤 本练习单人为一组。首先使用“快照 X”恢复 Linux 系统环境。注 实验步骤中涉及到的 mysql 数据库操作命令和 php 脚本源码,均在/opt/ExpNIS/HostSec-
14、Lab/Projects 目录中提供。一PHP 访问 MySQL 简单实例1. 创建隶属 test 数据库的 user 表(1)启动 mysql 服务在控制台中输入如下命令启动 mysql 服务。缺省状态下 root 用户密码为空。可通过如下命令查看 mysql 服务是否启动成功。(2)创建 user 数据库表在控制台中输入 mysql,进入 mysql 客户端控制台(mysql)。 选择工作数据库 test(缺少状态下,test 数据库已被创建)。 创建 user 数据库表 插入两条数据信息 查看数据库表2. 编写 PHP 脚本查询 user 数据库表编写 access.php 脚本,内容如
15、下:从代码中可知,当输入正确的用户名和密码后,就会提示登录成功,否则登录失败。单击桌面控制面板中“Web 浏览器”按钮,当我们在 URL 地址栏中提交:Web 页面会提示“登录成功”。写出此时 PHP 脚本中具体的 SQL 查询语句: 3. 实施 SQL 注入(1)在 URL 地址栏中提交:注入是否成功? 。写出此时 PHP 脚本中具体的 SQL 查询语句:(2)在 URL 地址栏中提交注入是否成功? 。写出此时 PHP 脚本中具体的 SQL 查询语句:通过分析 SQL 查询语句解释实验现象: 。(3)在 URL 地址栏中提交:注入是否成功?写出此时 PHP 脚本中具体的 SQL 查询语句:此
16、处利用了 MySQL 支持“#”注释格式的特性,在提交的时候会将#后面的语句注释掉。由于编码问题,在多数 Web 浏览器 URL 地址栏里直接提交#会变成空,所以这里使用了字符“#”的 ASCII 码值 0x23。(4)Mysql 还支持“/*”注释格式,请写出利用“/*”实现注入的 URL,以及此时的 SQL 查询语句。SQL 查询语句: URL: (5)步骤(2)通过向 username 注入逻辑 or 运算,在只需知晓用户名的情况下便可成功登录。下面请设计单独向 password 注入逻辑运算(可多个),要求在只需知晓用户名的情况下实现登录:SQL 查询语句: URL: (5)http:
17、/172.16.0.26/access.php?username=&password= or 1=1 and username=angel(6)下面请设计 SQL 查询语句,要求在不需要知晓用户名和密码的情况下实现登录。提示:通过猜测用户 ID 字段名称与用户序列号,结合逻辑运算,向 password 进行注入。SQL 查询语句: URL: (6)http:/172.16.0.26/access.php?username=&password= or 1=1 and userid=1二搜索引擎注入值得注意的是,Internet 上有许多的 PHP 程序搜索引擎是存在问题的,也就是提交特殊字符就可
18、以显示所有记录,包括不符合条件的。1. 创建隶属 test 数据库的 file 表(1)创建 file 数据库表file 数据库表结构如下:(2)插入四条数据信息title author summaryhoneypot paper honeypot and honeynetsnort paper snort intrusion detectionsnort based network ppi another snort paperiptables+snort no name intelligence ids2. 编写 HTML 页面通过 HTML 页面提交表单给服务器端 PHP 脚本,由
19、PHP 根据表单索引关键字对 MySQL数据库进行查询,最后将查询结果返回给 HTML 页面。HTML 页面代码如下:HTML 页面如图 15-1-1 所示。图 15-1-1 HTML 页面3. 编写 PHP 脚本查询 file 数据库表从代码中可知,search.php 会按 search.htm 提交的关键字对 file 数据库表进行模糊查询,并最终将查询结果显示在 HTML 页面中。输入关键字“snort”,进行搜索,搜索结果中含有多少条记录? 。记录中是否包含与 snort 关键字无关的项 。写出此时 PHP 脚本中具体的 SQL 查询语句:4. SQL 注入(1)这里我们利用 PHP
20、 脚本没有对关键字变量进行检查的漏洞进入 SQL 注入。输入关键字“%”,进行搜索,搜索结果中含有多少条记录? 。记录中是否包含与 snort 关键字无关的项 。写出此时 PHP 脚本中具体的 SQL 查询语句:解释 SQL 查询语句含义:(2)输入关键字“_ORDER BY fileid#”说明 “_”字符表示单字符通配,n 个“_”字符则表示 n 字符通配。“ORDER BY fileid”表示按特定顺序进行 SQL 查询。若 fileid 为整型字段,则按整数大小(由小到大)顺序进行查询;若 fileid 为字符数组类型字段,则按字符 ASCII 码(由前到后)顺序进行查询。写出此时 P
21、HP 脚本中具体的 SQL 查询语句:解释 SQL 查询语句含义:三注入实现导出文件本实验步骤仅为说明由于 SQL 注入而给服务器系统带来一定程度上的危害。在步骤一中,我们使用用户名,在无需知晓用户密码的情况下,通过 SQL 注入实现了登录。作为进一步操作,我们可以通过 SQL 注入来向服务器硬盘中写入大量无用的文件,而这是利用了 MySQL 的“INTO OUTFILE”命令,其查询方法如下:上述 SQL 查询语句会将 user 数据库表中,满足 cond 条件的记录以 INTO OUTFILE 标准格式导出到/etc/temp.txt 文件中。而信息能够被成功导出到/etc/temp.txt 中的条件是目标目录有可写的权限和目标文件不存在。基于步骤一,写出能够实现(SQL 注入)上述功能的 URL:写出此时 PHP 脚本中具体的 SQL 查询语句:四通过注入提升用户权限如果大家认为 SQL 注入仅仅适用于 SELECT 语句就大错特错了,其实还有两个危害更大的操作,那就是 INSERT 和 UPDATE 语句。(1)创建隶属 test 数据库的 register 表切换至/opt/ExpNIS/HostSec-Lab/Projects/step4/目录,执行脚本create_table_register 创建 register 数据库表。写出数据表包含的字段名称: 。