SQL注入攻击实验报告_林凯杰_200930601340
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
SQL注入攻击实验
【实验要求】
1)Sql注入攻击的实现与防御,其中防御模块为可选作部分。
2)要求:提交源代码和可执行文件,提供用户使用文档和实验报告文档(包括开发环境、运行主要截图、实验收获等说明)。
【实验原理】
1、结构化查询语言(SQL)是一种用来和数据库交互的文本语言,SQL Injection就是利用某
些数据库的外部接口把用户数据插入到实际的数据库操作语言当中,从而达到入侵数据库乃至操作系统的目的。
它的产生主要是由于程序对用户输入的数据没有进行细致的过滤,导致非法数据的导入查询。
2、SQL注入攻击主要是通过构建特殊的输入,这些输入往往是SQL语法中的一些组合,
这些输入将作为参数传入Web应用程序,通过执行SQL语句而执行入侵者的想要的操作,一般想要攻击成功,需要做到以下三点:
1)确定Web应用程序所使用的技术:注射式攻击对程序设计语言或者硬件关系密切,但是这些可以通过适当的踩点或者索性将所有常见的注射式攻击都搬出来逐个试一
下就知道了。
为了确定所采用的技术,攻击者可以考察Web页面的页脚,查看错
误页面,检查页面源代码,或者使用诸如Nessus等工具来进行刺探。
2)确定所有可能的输入方式:Web应用的用户输入方式比较多,其中一些用户输入方式是很明显的,如HTML表单;另外,攻击者可以通过隐藏的HTML表单输入、
HTTP头部、cookies、甚至对用户不可见的后端AJAX请求来跟Web应用进行交互。
一般来说,所有HTTP的GET和POST都应当作用户输入。
为了找出一个Web 应用所有可能的用户输入,我们可以求助于Web代理,如Burp等。
3)查找可以用于注射的用户输入:在找出所有用户输入方式后,就要对这些输入方式进行筛选,找出其中可以注入命令的那些输入方式。
这个任务好像有点难,但是这
里有一个小窍门,那就是多多留意Web应用的错误页面,很多时候您能从这里得
到意想不到的收获。
3、SQL注入攻击的特点。
4)变种极多:有经验的攻击者会手动调整攻击参数,致使攻击数据的变种是不可枚举的,这导致传统的特征匹配检测方法仅能识别相当少的攻击,难以防范。
5)攻击过程简单:目前互联网上流行众多的SQL注入攻击工具,攻击者借助这些工具
可很快对目标WEB系统实施攻击和破坏。
6)危害大:由于WEB编程语言自身缺陷以及具有安全编程能力的开发人员少之又少,大多数WEB业务系统均具有被SQL注入攻击的可能。
而攻击者一旦攻击成功,可以对控制整个WEB业务系统,对数据做任意的修改,破坏力达到及至。
4、SQL注入攻击过程。
1)判断Web环境是否可以SQL注入。
如果URL仅是对网页的访问,不存在SQL注
入问题,如:/162414739931.shtml就是普通的网页访问。
只有对数据库进行动态查询的业务才可能存在SQL注入,如:
/webhp?id=39,其中?id=39表示数据库查询变量,这种语句会在数据库中执行,因此可能会给数据库带来威胁。
2)寻找SQL注入点。
完成上一步的片断后,就要寻找可利用的注入漏洞,通过输入一
些特殊语句,可以根据浏览器返回信息,判断数据库类型,从而构建数据库查询语
句找到注入点。
3)猜解用户名和密码。
数据库中存放的表名、字段名都是有规律可言的。
通过构建特
殊数据库语句在数据库中依次查找表名、字段名、用户名和密码的长度,以及内容。
这个过程可以通过网上大量注入工具快速实现,并借助破解网站轻易破译用户密码。
4)寻找WEB管理后台入口。
通常WEB后台管理的界面不面向普通用户开放,要寻找
到后台的登陆路径,可以利用扫描工具快速搜索到可能的登陆地址,依次进行尝试,就可以试出管理台的入口地址。
5)入侵和破坏。
成功登陆后台管理后,接下来就可以任意进行破坏行为,如篡改网页、
上传木马、修改、泄漏用户信息等,并进一步入侵数据库服务器。
【实验环境】
操作系统:Windows 7 旗舰版
IDE :Myeclipse 8.6
服务器:Tomcat 7.0.11
数据库:SQLServer 2005
浏览器:搜狗浏览器3.2.0
【实验过程】
本次的实验过程主要用自己架设的网站进行SQL注入攻击的测试和防御。
1、新建网站SQLInjection项目,新建index.jsp进行SQL注入攻击演示。
这里以index.jsp为登陆界面,用户输入用户名和密码后进行登陆,获取参数后传递给LoginDeal(Servlet)进行处理,再根据处理的结果跳转到不同的页面。
1)页面预览如下:
2)这个页面的处理流程如下:
a)页面提交的用户名和密码通过表单提交,代码为
<form action="loginDeal" method="POST">
<input type="text" name="userName" value="用户名">
<input type="password" name="passwd">
</form>
b)当点击登陆后,即提交表单到loginDeal,在loginDeal里获取到userName
和passwd后调用com.sqlInjection.util.RequestDeal类进行登陆的验证,如果验证成功则跳转到welcom.jsp页面,如果失败则设置相应的提示信息后跳转回index.jsp页面。
c)RequestDeal进行验证的方法为利用userName和passwd两个参数构造查询
语句"select * from users where name='" + userName +"' and passwd='"
+ passwd + "'",查询后返回ResultSet set,如果set.next()为true,则表
示表中存在这样的一个记录,用户合法,所以验证成功。
3)这里用到的数据库为sqlinjection,用到的users表结构为:
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| name | varchar(25) | YES | | NULL | |
| passwd | varchar(35) | YES | | NULL | |
| permission | varchar(10) | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
其中name为用户名,passwd为密码,permission为等级。
4)正常的话用户输入自己的用户名和密码,如果正确则会跳转到welcome.jsp,如果
失败则会提示错误信息如下:
5)接下来我们进行简单的SQL注入攻击,我们可以通过最常用的‘和-- 来达到我
们的目的,实现任何用户在不知道密码的情况下进行登陆,我们可以通过用户名或者是在密码处进行查询语句的构造,以密码为例,使密码的结构为:
随机密码’ or 1=1 --
这里注意单引号不能丢失,因为密码的验证是字符串,所以在密码后面要补全语法中的单引号,然后加上永真的逻辑语句or 1=1 ,再用-- 注释掉原有语句后面还有的内容(注意-- 后面至少要有一个空格),这样一来,不管输入什么随机密码,只要表中有用户记录,那么查询的结果就一定会为真,也就是说一定能登陆成功。
6)用以上构建的密码尝试进行登陆,以kejack用户为例,用户名为:kejack,密码为:
1234’ or 1=1 -- ,如图(以下所有攻击的字串请手动敲入,复制单引号出错)
点击登陆后我们可以发现登陆成功了(正确的密码应该是kejack)
由此简单地用注入攻击绕过了用户的密码验证,得到了用户kejack的控制权,假设我们用这样的方法登陆admin帐号的话,那么就能得到admin的权限,进行非法的操作了。
7)接下来我们可以尝试通过SQL注入攻击添加一个管理员权限的用户,通过;来进行
SQL语句的批执行添加,这次我们以用户名为例,我们的目的不再是进行登陆,而是在于添加一个用户,所以不再关心登陆结构,构造语句如下:
kejack' ; insert into users values ('hake','hake','admin') --
通过;隔开后我们添加了一个添加用户的SQL语句,再注释掉之后的语句。
8)执行上面的注入语句结果如下:
在做这个多语句插入的过程中尝试了几次都失败,发现执行SQL语句的时候报错了,最开始的时候我用是MYSQL5.5做的实验,查找相关的材料才知道原来MYSQL默认是禁用了多语句执行的,在连接的时候要打开多语句执行许可才行,方法为更改jdbc驱动连接语句如下:
DriverManager.getConnection("jdbc:mysql://localhost:3306/sqlinjection?us er=root&password=kejack&allowMultiQueries=true");
后来发现MYSQL做不了xp_cmdshell的攻击改用SQLServer2005后则驱动的连接语句要改为:
DriverManager.getConnection("jdbc:sqlserver://localhost:1433;
DatabaseName=sqlinjection; allowMultiQueries=true","sa","");
设置了allowMultiQueries的值为真后再次进行试验就能成功了,此时查看mysql 中的users表,可以看到已经成功将新的用户插入到表中。
同样,在更换为sqlserver 后攻击也同样有效,可以看到表中新增加的值:
9)接下来要开始做的是xp_cmdshell注入攻击的实验,由于mysql没有这样的策略,
所以改用SQLServer2005,进行SQLServer 2005的配置要注意以下的问题:
a)安装SQLServer2005 以及SQL Server Management Studio。
b)到微软下载"Microsoft SQL Server 2005 JDBC Driver"最新版本,现在是4.0.
c)将解压后得到的sqljdbc_4.0文件夹放到c:\Program Files下。
d)把环境变量中的classpath后面加上sqljdbc4.jar的路径。
e)把sqljdbc4.jar包放到项目中并加入到java build path中,注意是sqljdbc4.jar
这个包而不是sqljdbc.jar,只有sqljdbc4.jar才支持JRE1.7(我的实验环境)。
f)打开SQL Server Management Studio,右键点击服务器,选择Properties(属
性),点击Security(安全性),server authentication服务器身份认证从windows authentication mode(windows身份认证模式)改为Sql Server and
Windows Authentication mode(SQL server和windows身份认证模式)。
g)回到SQL Server Management Studio服务器那,在服务器下双击打开
security(安全性) -- logins(登录名) ,右键选中sa,选择properties(属性),
点击Status(状态),在设置中将Login(登录)设置为Enabled(启用),这里需要
先设置一下sa的密码,否则无法启用,然后启用后再改回空。
h)打开SQL Server Configuration Manager”,双击“SQL Server 2005网络配
置”,点击“MSSQLSERVER 的协议”,如果“TCP/IP”没有启用,右键单击选
择“启动”,双击“TCP/IP”进入属性设置,在“IP 地址”里,可以配置“IPAll”
中的“TCP 端口”,默认为1433,将IP地址中的“已启用”设为“是”。
i)重启SQL Server服务。
10)改到SQLServer2005后要修改原来连接数据库的方式,以及原来业务处理的调用,
重新验证以上所做的攻击,均为有效,最终提交的版本使用的是SQLServer2005而不是mysql,接下来进行xp_cmdshell的攻击实验。
11)在这里我尝试使用以下的构造指令进行攻击
kejack'; exec master.dbo.xp_cmdshell 'net user hake 123456 /add' -- 运行前先要开启SQLServer 2005允许xp_cmdshell执行的权限,开启的代码如下:EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE;
GO
结果运行没报错,但是并没有看到新添加的帐户,多次修改都没有作用,后来在SQL Server Management Studio中执行这个指令出现以下的提示:
发生系统错误5。
NULL
拒绝访问。
NULL
NULL
看到拒绝访问想到应该是权限不够,但试着运行了下dir和copy等指令还是可以的,最后在网上发帖寻问,尝试了以下的方法后成功:打开SQL Server Configuration Manager,找到SQL Server 2005 服务,在右边的SQL server (SQLEXPRESS)打开后将原来的内置帐户调到本帐户,选一个本地主的用户并填好相应的密码,确定后重启服务。
12)服务重启后我们再来做一次攻击的实验,由于语句已经被修改在用户名处进行了截
断,所以后面的密码已经没有作用了,查询得到的结果由第二个语句产生了真值,所以登陆进来了。
再来看一下本地的帐户,我们可以看到此时已经多了一个我们创建的帐户了。
攻击成功,这样我们就得到了一个帐户,如果开启了远程控制的话,我们就可以远
程进行登陆做一些非法的破坏了。
当然我们还可以使用注入攻击备份数据库到指定的文件夹或者网络共享上,然后通过网络下载回来再进行用户的信息窃取。
2、SQL注入攻击的防范。
1)在这里我新建一个safeIndex.jsp作为防范SQL注入攻击演示的一个入口,链接到
safeLoginDeal进行登陆的验证操作。
2)针对第1部分6)小节的攻击的防范可以用以下的方式解决,修改验证的方式如下,
先用语句"select passwd from users where name='" + userName +"'"根据用户名得到密码,如果查询得到的密码跟用户输入的密码一样的话,则验证登陆成功,否则失败,这样一来就可以对上面的攻击进行防范了,因为密码已经不再参与到SQL 语句的构建中,所以攻击者只能在用户名上作功夫了,但这样的防范并不能完全的防范SQL注入攻击,因为还有用户名参与到构建中,可以通过用户名进行攻击。
3)登陆safeIndex.jsp,依然用kejack为用户名,1234’ or 1=1 -- 作为密码再次进
行登陆,可以发现现在已经无法通过密码进行注入攻击了。
4)从上面攻击的思路来看,我们也可以巧妙的做出一些防范的措施,首先,我们可以
在本地对SQLServer关闭xp_cmdshell的执行权限,给sa用户设置密码并且降低其权限为网络帐户,而非本帐户,针对以上攻击12)进行防御。
5)在界面限制用户的输入,比如说对用户名和密码的文本域通过maxlength属性进行
限制,这样用户在这个区域输入的信息长度就有限,没有足够的空间可以构建攻击的指令,当然这样的限制其实在本质上没有办法防御,因为其实了解http编程的人应该都明白,这些提交的内容都可以通过一些方法进行修改,所以任何在本地的限制和检查都是没有用的(比如我用httpClient模拟一个连接请求,伪造数据),只有在服务端进行控制才有效。
6)(简单又有效的方法)PreparedStatement:
采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值即可。
sql注入只对sql语句的准备(编译)过程有破坏作用,而PreparedStatement 已经准备好了,执行阶段只是把输入串作为数据处理,而不再对sql语句进行解析,准备,因此也就避免了sql注入问题。
7)字符串过滤:
public static boolean sql_inj(String str) {
String inj_str = "'|and|exec|insert|select|delete|update|
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
String inj_stra[] = inj_str.split("|");
for (int i = 0; i < inj_stra.length; i++) {
if (str.indexOf(inj_stra[i]) != -1) {
return true;
}
}
return false;
}
通过对敏感字符的检查看是否存在注入攻击。
8)当然也可以通过正则表达式进行匹配和字符的替换,原理跟7)都是一样的。
9)对信息进行加密,让攻击者就算获取得到用户信息也无法解读。
10)从根源开始处进行防御,基本上SQL注入攻击需要先获取到目标的配置,通过构造
不合法的语句来获取得到数据库的类型、表结构等等,大部分的信息是网页报错的时候泄露的,那么保护错误信息也就很重要了,像我写的采用MVC模式,报错只留在servlet,不会送往前端,那么攻击也就无从说起了。
11)对safeIndex.jsp进行完善后,safeIndex.jsp对以上的攻击都能成功防御,如下:
可以看到现在输入都已经受到限制,如果攻击者是通过模拟请求的话也不会成功,因为已经采用了PreparedStatement和字符检查了。
【实验小结】
1、此次的实验让我了解了SQL注入攻击的原理和过程,让我了解到了做这方面开发的
时候需要注意的安全性问题,也意识到安全的重要性和数据库的一些欠缺,提高了自己在这方面的安全意识。
2、此次实验最浪费时间的是从一开始就选择了mysql数据库进行实验,所以中途转到
SQLServer后又要重新验证之前的一些攻击。
3、在实验的过程中遇到了很多困难,配置上的,环境上的,还有一些需要注意的小问题,
而且从整个实验的过程来讲也涉及到了很多软件的配合使用。
4、整个实验过程花费的时间还是不少,需要做网页等,对于没有网页基础的我来说还是
有一定挑战性的,但整个实验的过程让我很感兴趣。
5、很高兴顺利完成了这次实验,期待下次能使用更高级的工具进行扫描和实施攻击,当
然,以后的开发过程中也要特别注意这些脆弱点了。
信息安全5班_林凯杰_200930601340。