记得大约是在2002年的时候,SQL Injection(SQL注入)开始有了最初的雏形。黑客们发现,在动态网页的某些地方(表单等……)插入一些可以在数据库查询中起作用的语句和符号,就可以让页面执行后,返回特殊的结果。于是,经过了2003的发展,到2004年,SQL Injection已经作为一种很成熟的入侵技术登上了安全界的舞台。也是2004年,有大批的网站程序被发现了SQL Injection漏洞,也有大批的网站栽倒在这种攻击手段之下。
下面,我就小行和逍遥一指令的帖子,作总结性的说明,仅供参考。
正如如小行所说的,在某些网站的登录界面,如果你知道了存在的用户名(例如:admin),你无须知道密码。只需在密码框中输入' or ''='即可。(注意,全是单引号!)这样在不知道密码的情况下,也可以用admin的身份登录。
但是,我想说的是,' or ''='在一些地方会出现问题。有些数据库不会认为“空”=“空”是成立的条件,这样就不行了。最好写成' or '1'='1
这样,SQL的查询语句,就变成了如下的样子。
select * from users where name='admin' and pass='123456' or '1'='1'
上面,蓝色的部分是用户在密码框中输入的数据。大家可以看见,由于用户的巧妙构造,使得SQL Server把这条查询语句解析为3个条件:
1、name='admin'
2、pass='123456'
3、'1'='1'
关键是中间的那个or,这样一来,SQL Server在解析的时候,只要条件2、3,符合一个就可以了。
因为1=1是衡成立的,所以这个查询的结果肯定是true。
<%
Dim Usr,Pwd
Usr=Request.form("username") '从表单获得数据
Pwd=Request.form("password") '同上
if (Usr<>"") and (Pwd<>"") then '判断数据为非空
Usr=Replace(Replace(Usr,"'",""),"or","") '嵌套了两个replace函数,过滤特殊字符
Pwd=Replace(Replace(Pwd,"'",""),"or","")
end if
%>
上面只是防范从表单提交的数据,对于一些新闻系统,经常会出现诸如: http://host/news/show.asp?id=1
之类的URL。
如果在那个1后面,加上一个单引号,一样会报错。我们往下看。
如果加上了单引号,SQL语句就变成了:
select * from news where id='1''
因为最后一个引号没有闭合,所以系统一定会报错。
防范如下(其实和上面的原理是一样D……)看代码:
<%
Dim id
id=Request("id")
if Not IsNumeric(id) then '------事先声明了变量,所以可以直接写进去。否则,就要写Request("id")
Response.write "Error!" '------反馈错误信息
Response.end '------中止执行下面的语句
end if
%>
方法2:在你的ASP语句中(一般是在最开头的地方),加上一句
On Error Resume Next
(注意,这句必须加在<% %>里面,不然IIS可不认。)
这就是著名的容错语句,当ASP语句执行时发生错误,就跳过错误,继续向下执行,而且不会返回错误信息。
当然,入侵者看不到错误信息,调试人员也看不到。所以,你一定在把一个ASP程序调试完毕后,再把这个语句加到ASP语句的顶端。否则,调试的时候,会烦死你的~~~~~~:O)
<%
user=request.form("userID")
pass=request.form("password")
for i=l to len(userID)
cl=mid(userID,i,l)
if cl="'"or us="="or" us="<"or us=">" then
response.redirect"提交非法字符,IP已经记录"
response.end
end if
next
%>自由 平等 共享
帖子51 精华0 积分126 阅读权限40 性别男 在线时间77 小时 注册时间2008-1-26 最后登录2008-6-22 查看详细资料TOP 您知道您年薪应是多少?
最简单的是用instr函数
这个东西好呀!instr函数
pwd = request.form("pwd")
name = request.form("name")
if instr(name,"'")<>0 or instr(pwd,"'")<>0 then
Response.Redirect "Loginsb.asp?msg=用户名/密码错误,请重新输入!"
response.end
end if
引用:
下面是引用haicao于06-12-2005 13:19发表的:
如果是asp+access结构的话.
过不过滤无所谓.
asp+access密码验证可以这样写
...
.....
.......
sql="select * from ad where user='"&user&"'"
rs.open sql,conn,1,1
if password=rs("password") then
成功登陆!
end if
user字段俺这么输:
admin' or password='123456
如果运气好,有个密码正好是123456的
在密码字段再输个 123456
不就进去了么?
对于字符输入,还是过滤的比较好,至少单引号必须过滤
这样一来,被单引号引起来的东西,无论如何躲不过去了
比如'&user&'
把单引号转换为& #39;
只要user字段输任何东西,都会当作字符串处理,而单引号一出现又被替换掉
那么该字段的注射就不可能了(愚见,请大家批评)
所以事实上很多的注射都是发生在数字型参数里,因为程序员总是记得对于数字型的参数,在SQL里是不需要用单引号引起来的,那么,即使进行了过滤,如果不充分,还是可以进行注射的.
比如在BBSXP上次的blog.asp中,有个id字段进行了过滤,但是,我们完全可以绕过去.
复制内容到剪贴板
代码:
if id<>"" then
sql="select * from [calendar] where id="&id&" order by id Desc"
虽然这个id变量过滤掉了'
不过对于AC的我们构造一个union查询
12 union select 1,2,username,userpass,5,6,7 from [user] where membercode=5
就可以查询区长的用户名和密码了,当然,修改条件查询任何人的密码也没问题的
对于MSSQL,union会出错,那么我们这么做:
12 and exists(select * from clubconfig where substring(adminpassword,1,1) between 0x30 and 0x46)
这样就跳过了单引号的限制,还有比较大小时用到的>和<符号
用二分法很容易得到所有数据,毕竟这种公开代码的程序的表的结构都很清楚
总结:
要防止用' or ''='登陆后台,应该说是要防止SQL 注射
防止SQL注射,个人认为最简单的注意方法有两个,1,检查所有输入,凡字符型,过滤掉单引号,并且用单引号引起来.
比如
user=replace(request(user),"'")
select * from admin where user='"&user&"'
如果是数字型,直接用
id=int (request(id))
select * from blog where id="&id&"
个人认为这样基本上就差不多了,有错误的地方欢迎大家指正个人论坛: http://www.xdxf.net
帖子60 精华2 积分3417 阅读权限100 性别男 在线时间134 小时 注册时间2005-5-3 最后登录2008-5-28 查看详细资料TOP
复制内容到剪贴板
代码:
objRs.open "Select * From [t4dmin] where cP4ssword='" & MD5(strPass)& "'",conn,1,1
If objRs.eof and objRs.bof Then
fError()
Else
bolIs = False
For i = 1 to objRs.RecordCount
If objRs("c4dmin")=strName then
bolIs = True
Exit For
End If
Next
If bolIs = False Then
fError()
Else
session("IsAdmin")=True
response.Redirect("admin.asp")
End If
End If
objRs.close那些好像永远都不会停的雪。那一季永远不结束的冬天。
帖子38 精华2 积分95 阅读权限100 性别男 来自BugCenterTeam 在线时间33 小时 注册时间2005-3-3 最后登录2008-1-18 查看个人网站 查看详细资料TOP
我觉得职业欠钱说得有点搞笑了吧?
user字段俺这么输:
admin' or password='123456
...
你为什么不直接用户名输入admin
密码框输入123456呢?
再说了
sql="select * from ad where user='"&user&"'"
rs.open sql,conn,1,1
if password=rs("password") then
有没看到还有一个判断密码字段和用户输入的是否一致的检查,可不是简单的
if not(rs.eof and rs.bof)的判断呀,晕!在我纯真年少時,有一個女生,她願意爲我失去生命,她意志堅定地說:你再纏著我,我就去死! 在我負笈外地時,有一個女生,她願意等我到下輩子,她溫柔婉約地說:你想成爲我男友?等下輩子!! 在我窮困潦倒時,有一個女生,她願意與我共赴黃泉,她眨著紅眼說:你再不還錢,我和你同歸于盡!
帖子428 精华24 积分5194 阅读权限200 性别男 在线时间164 小时 注册时间2004-10-5 最后登录2008-7-13 查看详细资料TOP
防范的方法很多嘛
1.破坏构造的字符串
(1) MD5加密:不管怎么样,字符串都将转换成MD5值,不存在与SQL语句冲突的问题.当然,如果是MSSQL的话,用户名要放在句后,以防一些人用;--注释掉MD5的Hash(一般有MD5存在的,ACCESS饶不过应该,MSSQL可以看先后次序)
(2) 过滤特殊字符,比如replace(username,"'","") | replace(username,"--","")之类的..(网上N多系统这么过滤)
2.将数据与字符串比对
先查看是否eof,如果不是,那么将数据库中取出一个未知的值与输入的值比对.如果相同,则可以说明正确...也是杜绝的办法(看过一个叫ET-Comic的代码使用这种方法)
3.先取出再验证
一个比较低效率的办法...来一个循环,然后读出数据比对...输入的字符串本身不参与查询...(很早的时候看一个文章系统用过..)me=\"kEvin1986\" & chr(0) & \"at solitude\" msgbox len(me) \' You can see somthing. msgbox me \' But just part of it. \'i think i will hide part of myself
帖子325 精华12 积分3936 阅读权限100 性别男 在线时间308 小时 注册时间2005-2-5 最后登录2007-9-3 查看个人网站 查看详细资料TOP
楼上的方法只是在做表面...其实是可以修改提交参数的me=\"kEvin1986\" & chr(0) & \"at solitude\" msgbox len(me) \' You can see somthing. msgbox me \' But just part of it. \'i think i will hide part of myself
帖子325 精华12 积分3936 阅读权限100 性别男 在线时间308 小时 注册时间2005-2-5 最后登录2007-9-3 查看个人网站 查看详细资料TOP