ASP 安全编程一些注意事项

Table of Contents

很多人抱怨 ASP 安全不高、速度不快,其实 ASP 也很优秀。用 PHP 一样可以写出拉圾程序,用 ASP 依然可以写出很优秀的程序。安全高不高取决于编程者,PHP依然可以写出漏洞百出的程序,所以,别抱怨 ASP 这样那样的毛病,我写 ASP 已经三年多了,一直都认为它很方便,虽然有些地方写着很复杂,及不上 PHP,因为这样,ASP 写着感觉更爽。把多年总结的一些 ASP 常见的安全事项写出来。

1. 古老的绕验证漏洞

虽然古老,依然存在于很多小程序之中,比如一些企业网站的后台,简单谈谈。这个漏洞出现在没有对接受的变量进行过滤,带入数据库判断查询时,造成SQL语句的逻辑问题。例如以下代码存在问题:

username=request("username")
password=request("password")
sql = "select * from user where username='" & username & "' and
password='" & password & "'"

很容易看出在没有对 username、password 进行过滤就带入 SQL 语句进行判断了,提交 'or''=',SQL 语句就变成了:

select * from user where username=''or''='' and password=''or''=''

返回值为 ture。

一般在登录处过滤字符,代码如下:

replace(request.form("username"),"'","")
replace(request.form("password"),"'","")

上面指定了 POST 方式接受提交过来的数据,指定接受方式很重要,下面谈谈。

2. 指定接受数据提交方式

ASP 中的 Request 对象可以接受 GET、POST、COOKIES 请求。将其简化写成 **=Request("参数") 的格式接受数据,此时 Web 接受数据时先以 GET 方式接受,如果不匹配再以 POST 方式接受,最后再以 Cookies 方式接受。也就是 Cookies 注射造成的原因。

指定接受方式不仅可以避免 Cookies 注射,还可以提高 Web 处理的速度。

一个存在问题的代码如下:

id=request("id")
sql="select * from Articles where id="&id&""
set rs=conn.execute(sql)

这里不管 id 过滤没有过滤,关键是 id 接受时没有指定接受方式,造成了 Cookies 注射。

这样写:

id=request.QueryString("id")
sql="select * from Articles where id="&id&""
set rs=conn.execute(sql)

id 使用了 get 方式接受数据。

3. HtmlEnCode

HtmlEnCode 是 ASP 中 Server 的一个对象,可以直接格式化 HTML 不被执行在浏览器上,比如以下代码:

<%
lx="<script>alert('test')</script>"
response.write lx
%>

最后浏览时弹出提示窗口。

如果改成以下代码:

<%
lx="<script>alert('test')</script>"
lx=Server.HtmlEncode(lx)
response.write lx
%>

浏览器直接显示 <script>alert('test')</script>,HTML 代码直接被格式化了。

这个对象很有用,一般在接受数据不需要使用 HTML 代码格式的情况下,直接使用它进行过滤。比如搜索结果显示、留言板等等。如:

test=request.QueryString("test")
response.write test

以上代码中,test 没有进行过滤直接显示了,如果 test 接受一个内容为 <script>alert("test")</script> 时,代码被执行,就会弹出一个内容为 test 的提示。改写为下:

test=server.htmlencode(request.QueryString("test"))
response.write test

那么再次提交 <script>alert("test")</script>,浏览器就显示一段字符“<script>alert("test")</script>”。

4. 注射漏洞

注射方面就不多介绍了,介绍起来太多了,大家也很熟悉,直接说防范方法,有问题的代码如下:

id=request("id")
sql="select * from Articles where id="&id&""
set rs=conn.execute(sql)

明显 id 不进行过滤带入了 SQL 查询,最简单的方法就是判断 id 是否为整型数据,代码如下:

id=Request("id")
if Not IsNumeric(id) then    '这里用IsNumeric判断id是否为整型
Response.write "错误提交"
Response.end
else
sql="select * from Articles where id="&id&""
set rs=conn.execute(sql)
end if

还可以使用判断提交内容是否含有非法字符,直接贴代码,代码是以前小蓝的 Tryaspwebsystem 程序中的防注射代码,经过我们两个改了又改:

<%
dim sql_injdata
SQL_injdata = "'|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare"
SQL_inj = split(SQL_Injdata,"|")

'get拦截
If Request.QueryString<>"" Then
For Each SQL_Get In Request.QueryString
For SQL_Data=0 To Ubound(SQL_inj)
if instr(LCase(Request.QueryString(SQL_Get)),Sql_Inj(Sql_DATA))>0 Then
Response.Write "非法提交"
Response.end
end if
next
Next
End If

'post注入拦截 If Request.Form<>"" Then
For Each Sql_Post In Request.Form
For SQL_Data=0 To Ubound(SQL_inj)
if instr(LCase(Request.Form(Sql_Post)),Sql_Inj(Sql_DATA))>0 Then
Response.Write "非法提交"
Response.end
end if
next
next
end if
on error resume next
%>

上面代码中没有看到防范 Cookies 注射的?前面说了,指定了接受方式就没问题了。

5. 字符过滤

一般用来防止跨站,定义一个结构,将非法的字符全部替换了:

function Str( data )
Str = replace( data, "'", "''" )
Str = replace( Str, "&", "&" )
Str = replace( Str, " ", " " )
Str = replace( Str, "<", "&lt;" )
Str = replace( Str, ">", "&gt;" )
Str = replace( Str, VbCr, "<br>" )
Str = replace( Str, "'", "'" )
Str = replace( Str, CHR(34), """ )
end function

直接用 str(request("*")) 的方法调用过滤。

如果要还原为正常显示,代码如下:

function Str1(data)
Str1 = replace( data, "'", "''" )
Str1 = replace( Str1, "&", "&" )
Str1 = replace( Str1, " ", " " )
Str1 = replace( Str1, "&lt;", "<" )
Str1 = replace( Str1, "&gt;", ">" )
Str1 = replace( Str1, "<br>",VbCr  )
Str1 = replace( Str1, "'","'"  )
end function

6. 数据库防下载

只要将数据库的扩展名删除,就可以做到防下载了。大家都知道 IIS 里有个默认文档,当用户浏览网站主页或者网站目录时,首先浏览的就是这默认文档,一般为 index.htm、index.asp 等等。如果删除了扩展名,那么直接提交数据库地址时,就会被误认为浏览目录,但这个目录并非存在,所以 404 错误,返回找不到该页。举例:假设我们取数据库名为“luanx”(没有扩展名),然后通过访问地址 http://**/luanx ,假设默认文档最前面的一个是 index.htm,在访问时会被解析为 http://**/luanx/index.htm ,因为此目录不存在而找不到(测试环境是 Windows XP/2003,IIS 5.0/6.0,FAT32/NTFS 的硬盘)。此方法只用于 Windows 2003 的服务器,XP 下还是能下载,不过没几个人用 XP 架设服务器的。

7. 暴库防范

暴库这个大家都知道,在数据库连接文件中加入一句错误处理就可以了:On Error Resume Next

8. 上传漏洞防范

直接使用 lcase 函数,该函数从右截取指定个数的字符串,截取后进行判断。关于上传漏洞不建议过滤扩展名,而是直接判断是否为指定的扩展名,代码如下:

file=lcase(right(file.filename,4))
if file<>".gif" and file<>".jpg" then
response.write "文件格式不对" response.end
end if

9. User-agent 的安全

可以直接参考http://luanx.blogbus.com/logs/30631254.html

加上这一点注意的目的是想让大家感受到任何输入、输出都不是可信任的。

10. 杂七杂八

除了以上,还要注意一些问题:

1、后台路径更改。

2、密码用 MD5 加密。

3、数据库表段不要用一些常见的,容易被猜出来。

4、任何数据库名都要修改,特别是一些编辑器或者网上下的第三方面程序加入在自己程序中的。

5、别被社工就 OK 了。

关于 ASP 安全方法总结这么多了,以上都是 ASP 安全编程中的最基础,也是核心,要记住任何输出、输入的都可能是危险的,都要进行过滤,其实脚本安全搞着很有趣,欢迎大家讨论不足或者提出更多。