不可饶恕错误之关键字未过滤
技术与开发
编者语:金融危机的到来让许多程序员也受到影响,在这样的大环境下,程序员还有好的机遇吗?有!而且是非常大的机遇!当前移动平台的程序开发如火如荼,特别是在苹果、Google等推出了平台开发工具后,进入这一领域的程序员越来越多,有的是想赚一些外快,有的是想在移动平台上功成名就,成为马化腾第二。
机遇就在眼中,你整装待发了吗?在此之前,还有什么需要注意的?小编跟之前进入此领域的程序员们交流时,他们首先给出的是忠告,编程时要避免犯一些不必要的错误,留下安全漏洞,造成功亏一篑。那又有哪些错误是我们需要避免的呢?看了不可饶恕编程错误系列,你就可以正式“出征”了!
数动连线程序员唐忠超:前些年有一款叫做《许愿池》的插件,很多论坛都安装过,它是一款非常好玩的游戏,可以让论坛用户在网上许下自己的心愿。但是它也一度让论坛管理员非常恐惧,纷纷放弃这款插件,这是为什么呢?
该插件的作者在编写程序时,对SQL的关键字过滤不严,导致SQL注入漏洞出现,安装了该插件的论坛也由此产生了严重的安全隐患,被黑客入侵,出现了论坛数据被窜改,用户流失的严重后果。
错误产生原因
如果对SQL命令的关键字过滤不严,别有用心的人就可以输入恶意的SQL命令让服务器执行,他从而获得某些特殊的操作权限,这样就导致了SQL注入漏洞的出现。
假如某网站的某条新闻的页面网址是http://***.com/view.asp?id=123,当用户访问这条新闻的时候,该网站的服务器将执行一条类似"select * from 新闻表名 where ID=" & id的语句。
如果程序员对参数id的值没有进行过滤,那么访问该网址的用户故意提交下面这样的网址:http://***.com/view.asp?id=123 and user>0 ,这时,服务器执行的SQL命令就变成了“select * from 新闻表名 where ID=123 and user>0”,服务器会返回错误提示,而错误提示中就暴露了许多重要的信息。得到这些信息后,黑客就可以进一步攻击网站,企图获得网站管理密码以及服务器管理权限等。
错误代码分析
原理容易懂,但是在编写具体代码时,还是容易忽视关键字过滤。下面我们来看几个典型的关键字未过滤的错误代码。
代码1:未对输入的数字信息进行过滤
if trim(request("id"))="" then
response.Write("")
response.End()
end if
cn.Execute "delete from [admin] where id ="&request("id")
cn.close
上面的这段代码的作用是删除一条记录,它只做了防止录入id值为空的验证。当id值为数字时,它将成功执行,但如果有人提交的id值为“1 or id>0”时,我们来看看这段代码将要执行的语句:cn.Execute "delete from [admin] where id =1 or id>0", 不难看出,它是一段可执行的语句,并且会违背原程序的意思,将整个admin表的数据都清空了。
正确代码应该是:
if trim(request("id"))="" then
response.Write("")
response.End()
end if
if not isnumeric(request("id")){'判断输入信息是否为数字,以防止SQL注入,达到过滤的效果
response.Write("参数错误!")
response.End()
}
cn.Execute "delete from [admin] where id ="&request("id")
cn.close
代码2:未对输入的字符串信息进行过滤
rs.open "select * from [message] where title like '%"& request("tit")&"'",cn,1,1
if rs.eof then
response.Write "没有记录!"
else
...
End if
上面的这段代码的作用是模糊查询值为tit的title字段的键值。它没有对tit的值进行过滤,当然这里提交“1 or id>0”时,程序会把它作为字符串处理而不产生SQL注入错误,但是我们不要高兴得太早了,攻击者如果提交tit的值为“1 ' ; and db_name()>0 and 1= '1”,
那么执行的代码就是:rs.open "select * from [message] where title like '%1 ' ; and db_name()>0 and 1= '1'",cn,1,1程序在执行这段代码后,会产生报错信息,db_name()是一个SQLServer系统变量,返回的是连接的数据库名。
正确代码应该是:
tit= replace(request("tit"),"'","''") '替换掉SQL的关键字"'"
rs.open "select * from [message] where title like '%"& tit&"'",cn,1,1
if rs.eof then
response.Write "没有记录!"
else
...
End if
小编支招
首先,要对客户端输入的信息进行合法验证,不能因为开发任务重、开发时间紧迫等原因,草率验证。一般而言,我们要验证用户输入的信息不含有数据库关键字或者符号,常见的有:“'、exec、insert、
select、delete、from、update、count、user、xp_cmdshell、add、net、Asc”。
其次,在验证时要注意大小写形式,有些程序员过滤了小写的关键字,却偏偏忘记了过滤大写的关键字。此外,对于重要的权限密码,最好采用加密形式储存到数据库中,如MD5不可逆加密等,就算产生了SQL注入错误,显示的也只是加密后的密码,对于系统权限保护,起到了一定作用。
最后,为了避免出现“SQL注入错误”所带来的风险,如果我们有服务器的权限,应该将程序报错信息屏蔽掉,例如将错误提示统一设置为HTTP500错误,这样将大大加大攻击者的攻击难度。