论文部分内容阅读
引言
随着Internet技术的迅猛发展,为了能更充分地使用互联网这个世界上最大的交流平台,许多单位或个人争相建立了自己的网站。为了与广大用户更好地进行交流,大多数网站又采用了动态网站编程技术。在众多的网站开发技术中,由于Microsoft的ASP的简单易用,所以成为众多网站程序员的首选。但是,一些程序员在编程时不够注意安全方面,所以经常出现因一个变量未过滤,造成网站被“注入”,导致整台服务器沦陷的事实。
下面我基于ASP源代码对注入漏洞发生的原理做进一步的阐述。
1 剖析SQL注入漏洞(SQL Injection)
1.1什么是SQL注入
由于某些程序员在编程时,没有对用户输入数据的合法性进行判断,使攻击者可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据,这就是所谓的SQL Injection,即SQL注入,又叫SQL注射。由于SQL注入是从正常的WWW端口访问,而且表面看起来跟一般的Web页面访问没什么区别,目前普通的防火墙都不会对SQL注入发出警报,如果管理员没查看IIS日志的习惯,可能被入侵很长时间都不会发觉。
SQL注入漏洞从提交数据的方式可以分为三类:Get、Post和Cookies,其中出现最普及的当属Get方式的注入。从变量类型又可以分为数字型注入和字符型注入。
1.2 Get方式注入原理
下面是一段存在Get注入的代码:
<!--#include file="conn.asp"-->
<%id= request.querystring("id")
set rs=Server.CreateObject("ADODB.RecordSet")
sql="select * from class where classid="&id
rs.open sql,conn,1,1
rs.close
set rs=nothing
%>
通过代码,我们看到id参数从URL传进来后,没有经过任何过滤,就进行数据查询,从而产生了经典的SQL注入漏洞。比如攻击者可以提交如下数据:
id=1 and exists(select * from admin)
那么数据库查询语句(上面的sql 变量)就变成:
sql="select * from class where classid=1 and exists(select * from admin)"
我们知道classid=1为真(假设数据库表中有此数据),由于“and”表示“与”的关系,那么:
classid=1 and exists(select * from admin) 的真伪只取决于exists(select * from admin)
简单地说就取决于admin表是否存在。如果网页返回的正常,则admin表存在,反之则不存在。那么攻击者就达到了猜测管理员表名的目的。
1.3Post方式注入原理
Post注入是通常针对采用Post提交的表单进行的注入,很多情况下都是字符型的变量,而且它没有Get方式注入那样容易察觉,下面是一段存在Post注入的表单:
<tr>
<td width="102" height="25" align="right">邮箱地址:</td>
<td width="198" height="25"><input name="email" type="text" id="email">
<input name="login" type="hidden" value="yes"></td>
</tr>
<tr>
<td height="25" align="right">访问密码:</td>
<td height="25"><input name="password" type="password" id="password"></td>
</tr>
这是一个普通用户的登录界面,提交进行数据库处理的代码如下:
<%if request.form("login")="yes" then
set rs=server.createobject("adodb.recordset")
sql="select * from book where xx='"&request.form("email")&"' and
password='"&request.form("password")&"' order by id desc"
rs.open sql,conn,1,1
if not rs.eof then
session("login")="yes"
session("email")=request.form("email")
session("password")=request.form("password")
end if
rs.close
set rs=nothing
end if
%>
仍然可以看到,变量"email"没有经过过滤直接用request.form("email")取值后就进行数据库查询,当攻击者在"email"对应的登录框中提交:
'or exists(select * from admin) or '1'='1
那么数据库查询语句sql就变成:
select * from book where xx=' 'or exists(select pwd from admin) or '1'='1' and password='"&request.form("password")&"'order by id desc
在SQL中and 的优先级是比or高的,而xx=' '显然为假,exists(select pwd from admin)真伪待定,'1'='1'为真,因为我们没有输入密码,所以password='"&request.form("password")为假。那么在where后面的语句的真实性如下:
假 or 待定 or (真 and 假) 等价于 假 or 待定 or 假,所以where后面语句的真伪再次取决于攻击者输入的查询语句,如果admin表中pwd字段存在就登录成功,反之则失败。攻击者就可以在不用知道管理员密码的情况下猜测管理员密码。
1.4Cookies方式注入原理
Cookies注入的方式是最近流行的一种注入方式,下面是一段典型的存在Cookies注入的代码,其中check_sql.asp是一段网上流传的通用防注入的代码3.0版,通过它可以有效防止Post和Get方式的注入漏洞,但是却忽略了Request.Cookies的注入方式。
<!--#include file="check_sql.asp"-->
<% id= request ("id")
set rs=Server.CreateObject("ADODB.RecordSet")
sql="select * from class where classid="&id
rs.open sql,conn,1,1
rs.close
set rs=nothing
%>
攻击者可以直接在浏览器的地址栏去掉URL,然后输入:
javascript:alert(document.cookie="id="+escape(and exists(select * from admin))
来修改cookies值,然后再去掉修改cookie的语句,再加上原来的不传递任何参数的URL,这样修改了的cookies就会提交给id= request ("id"),又由于id= request ("id")没有具体指明是Request.QueryString或Request.Form,这样就给了攻击者利用的方式。我们知道 ASP中Request对象在省略具体的集合名称而直接使用"id=request("id")"来获取数据时,总是按Request.QueryString,Request.Form,Request.cookies,Request.servervariables集合的顺序来搜索的,而cookies是可以在客户端进行修改,这样一来,攻击者就可以使用诱使服务器接收Request.cookies方式提交变量的值,从而利用绕过通用防注入程序进行注入攻击。
判断方式和Get方式一样。如网页返回的正常,则admin表存在,反之则不存在。那么攻击者就达到猜管理员表名的目的了。
2 SQL注入漏洞的防范
通过以上分析我们看到,对于以上三种注入方式,参与数据库查询的变量不外乎就是数字型和字符型,所以分别针对数字型和字符型来做防范。
2.1针对数字型的变量
针对数字型的变量,我们可以判断其是否真是数字型变量,如上面的Get注入方式(Get方式也有字符型的变量,原理一样)。参考代码如下:
If not isNumeric(Parameter) then
Response.write "<script>alert(/参数只能为数字/)</scirpt>"
2.2针对字符型的变量
针对字符型的变量,因为攻击者是试图通过闭合单引号来达到目的,所以我们只要可以过滤单引号就可以防止注入,如上面的Post注入方式(Post方式也有数字型的变量,原理一样)。 参考代码如下:
Parameter=replace(Parameter,"'","")
3 结束语
其实SQL注入造成的危害远没有猜个列名或表名那么简单。对于Access数据库,可以直接用Union查询找出管理员密码;对于SQL Server,利用方法更多,如果注入点是SA权限,一般可用xp_cmdshell直接执行系统命令,如果注入点是DB_Owner权限,也可列目录备份得到Webshell。
由于当前的注入工具泛滥,而针对网站的攻击很多都是从注入开始的,但是我们也不必谈注入“色变”。只要了解了SQL注入产生的根本原因,就能找到应对之策。其实PHP和JSP也存在注入,原理大致和ASP一样,只是不同环境在利用方式上略有不同罢了。我们只要掌握原理,就可以触类旁通,编写出更加安全的代码,为祖国网络安全尽一份力量。
随着Internet技术的迅猛发展,为了能更充分地使用互联网这个世界上最大的交流平台,许多单位或个人争相建立了自己的网站。为了与广大用户更好地进行交流,大多数网站又采用了动态网站编程技术。在众多的网站开发技术中,由于Microsoft的ASP的简单易用,所以成为众多网站程序员的首选。但是,一些程序员在编程时不够注意安全方面,所以经常出现因一个变量未过滤,造成网站被“注入”,导致整台服务器沦陷的事实。
下面我基于ASP源代码对注入漏洞发生的原理做进一步的阐述。
1 剖析SQL注入漏洞(SQL Injection)
1.1什么是SQL注入
由于某些程序员在编程时,没有对用户输入数据的合法性进行判断,使攻击者可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据,这就是所谓的SQL Injection,即SQL注入,又叫SQL注射。由于SQL注入是从正常的WWW端口访问,而且表面看起来跟一般的Web页面访问没什么区别,目前普通的防火墙都不会对SQL注入发出警报,如果管理员没查看IIS日志的习惯,可能被入侵很长时间都不会发觉。
SQL注入漏洞从提交数据的方式可以分为三类:Get、Post和Cookies,其中出现最普及的当属Get方式的注入。从变量类型又可以分为数字型注入和字符型注入。
1.2 Get方式注入原理
下面是一段存在Get注入的代码:
<!--#include file="conn.asp"-->
<%id= request.querystring("id")
set rs=Server.CreateObject("ADODB.RecordSet")
sql="select * from class where classid="&id
rs.open sql,conn,1,1
rs.close
set rs=nothing
%>
通过代码,我们看到id参数从URL传进来后,没有经过任何过滤,就进行数据查询,从而产生了经典的SQL注入漏洞。比如攻击者可以提交如下数据:
id=1 and exists(select * from admin)
那么数据库查询语句(上面的sql 变量)就变成:
sql="select * from class where classid=1 and exists(select * from admin)"
我们知道classid=1为真(假设数据库表中有此数据),由于“and”表示“与”的关系,那么:
classid=1 and exists(select * from admin) 的真伪只取决于exists(select * from admin)
简单地说就取决于admin表是否存在。如果网页返回的正常,则admin表存在,反之则不存在。那么攻击者就达到了猜测管理员表名的目的。
1.3Post方式注入原理
Post注入是通常针对采用Post提交的表单进行的注入,很多情况下都是字符型的变量,而且它没有Get方式注入那样容易察觉,下面是一段存在Post注入的表单:
<tr>
<td width="102" height="25" align="right">邮箱地址:</td>
<td width="198" height="25"><input name="email" type="text" id="email">
<input name="login" type="hidden" value="yes"></td>
</tr>
<tr>
<td height="25" align="right">访问密码:</td>
<td height="25"><input name="password" type="password" id="password"></td>
</tr>
这是一个普通用户的登录界面,提交进行数据库处理的代码如下:
<%if request.form("login")="yes" then
set rs=server.createobject("adodb.recordset")
sql="select * from book where xx='"&request.form("email")&"' and
password='"&request.form("password")&"' order by id desc"
rs.open sql,conn,1,1
if not rs.eof then
session("login")="yes"
session("email")=request.form("email")
session("password")=request.form("password")
end if
rs.close
set rs=nothing
end if
%>
仍然可以看到,变量"email"没有经过过滤直接用request.form("email")取值后就进行数据库查询,当攻击者在"email"对应的登录框中提交:
'or exists(select * from admin) or '1'='1
那么数据库查询语句sql就变成:
select * from book where xx=' 'or exists(select pwd from admin) or '1'='1' and password='"&request.form("password")&"'order by id desc
在SQL中and 的优先级是比or高的,而xx=' '显然为假,exists(select pwd from admin)真伪待定,'1'='1'为真,因为我们没有输入密码,所以password='"&request.form("password")为假。那么在where后面的语句的真实性如下:
假 or 待定 or (真 and 假) 等价于 假 or 待定 or 假,所以where后面语句的真伪再次取决于攻击者输入的查询语句,如果admin表中pwd字段存在就登录成功,反之则失败。攻击者就可以在不用知道管理员密码的情况下猜测管理员密码。
1.4Cookies方式注入原理
Cookies注入的方式是最近流行的一种注入方式,下面是一段典型的存在Cookies注入的代码,其中check_sql.asp是一段网上流传的通用防注入的代码3.0版,通过它可以有效防止Post和Get方式的注入漏洞,但是却忽略了Request.Cookies的注入方式。
<!--#include file="check_sql.asp"-->
<% id= request ("id")
set rs=Server.CreateObject("ADODB.RecordSet")
sql="select * from class where classid="&id
rs.open sql,conn,1,1
rs.close
set rs=nothing
%>
攻击者可以直接在浏览器的地址栏去掉URL,然后输入:
javascript:alert(document.cookie="id="+escape(and exists(select * from admin))
来修改cookies值,然后再去掉修改cookie的语句,再加上原来的不传递任何参数的URL,这样修改了的cookies就会提交给id= request ("id"),又由于id= request ("id")没有具体指明是Request.QueryString或Request.Form,这样就给了攻击者利用的方式。我们知道 ASP中Request对象在省略具体的集合名称而直接使用"id=request("id")"来获取数据时,总是按Request.QueryString,Request.Form,Request.cookies,Request.servervariables集合的顺序来搜索的,而cookies是可以在客户端进行修改,这样一来,攻击者就可以使用诱使服务器接收Request.cookies方式提交变量的值,从而利用绕过通用防注入程序进行注入攻击。
判断方式和Get方式一样。如网页返回的正常,则admin表存在,反之则不存在。那么攻击者就达到猜管理员表名的目的了。
2 SQL注入漏洞的防范
通过以上分析我们看到,对于以上三种注入方式,参与数据库查询的变量不外乎就是数字型和字符型,所以分别针对数字型和字符型来做防范。
2.1针对数字型的变量
针对数字型的变量,我们可以判断其是否真是数字型变量,如上面的Get注入方式(Get方式也有字符型的变量,原理一样)。参考代码如下:
If not isNumeric(Parameter) then
Response.write "<script>alert(/参数只能为数字/)</scirpt>"
2.2针对字符型的变量
针对字符型的变量,因为攻击者是试图通过闭合单引号来达到目的,所以我们只要可以过滤单引号就可以防止注入,如上面的Post注入方式(Post方式也有数字型的变量,原理一样)。 参考代码如下:
Parameter=replace(Parameter,"'","")
3 结束语
其实SQL注入造成的危害远没有猜个列名或表名那么简单。对于Access数据库,可以直接用Union查询找出管理员密码;对于SQL Server,利用方法更多,如果注入点是SA权限,一般可用xp_cmdshell直接执行系统命令,如果注入点是DB_Owner权限,也可列目录备份得到Webshell。
由于当前的注入工具泛滥,而针对网站的攻击很多都是从注入开始的,但是我们也不必谈注入“色变”。只要了解了SQL注入产生的根本原因,就能找到应对之策。其实PHP和JSP也存在注入,原理大致和ASP一样,只是不同环境在利用方式上略有不同罢了。我们只要掌握原理,就可以触类旁通,编写出更加安全的代码,为祖国网络安全尽一份力量。