Cookies 欺骗漏洞的防范方法(vbs+js 实现)


  本文标签:Cookies,欺骗漏洞,防范

最后罗嗦一句,本人录入这篇文章用的机器上没有 ASP 环境,所以提供的代码未能进行测试,对这一点本人深表歉意 。如果大家发现了代码中的任何问题,欢迎拍砖~本人皮厚~
一、攻击原理
Cookies 欺骗主要利用当前网络上一些用户管理系统将用户登录信息储存在 Cookies 中这一不安全的做法进行攻击,其攻击方法相对于 SQL 注入漏洞等漏洞来说相对要“困难”一些,但还是很“傻瓜” 。
我们知道,一般的基于 Cookies 的用户系统至少会在 Cookies 中储存两个变量:username 和 userlevel,其中 username 为用户名,而 userlevel 为用户的等级 。当我们的浏览器访问 ASP 页面时,它会传出类似
GET /.../file.asp HTTP 1.0
...
Cookies: username=user&userlevel=1
...
的数据包,那么,我们只要知道了管理员的 username 和 userlevel 值(假设分别为 admin 和 5),便可以通过传输
GET /.../file.asp HTTP 1.0
...
Cookies: username=admin&userlevel=5
...
来获取管理员权限 。很简单是不是?然而,在这个漏洞被发现之前,几乎所有的用户管理系统都依赖于 Cookies 。
二、安全地储存用户信息
既然 Cookies 是不安全的,而我们又必须把用户登录信息存储下来,那么应该存储在什么地方呢?
我们注意到,在 ASP 中,除了 Cookies 外,还有 Session 可以储存信息 。Session 是储存在服务器上的,不是客户端随随便便就能够更改的,所以具有极高的安全性 。这样,大家就可以把所有 Cookies 的代码均换作 Session 了 。
三、长时间储存用户信息
采用 Session 来保存用户登录信息,虽然摆脱了 Cookies 欺骗的问题,但是 Session 不能长期储存(IIS 默认 Session 在用户停止响应 20 分钟后失效),于是产生了这一节所述的 Cookies + Session 混合存储法 。
这一方法有两个变种,第一种是在 Cookies 中储存用户名和密码,当用户访问一个页面时,先读取 Session,如果有内容则以 Session 为准,否则读取 Cookies,按照 Cookies 中提供的用户名和密码进行“不透明”的登录一次,用以判断 Cookies 中的内容是否合法,若合法再进而存入 Session 中 。实现这一方法的代码如下:
vbs:
复制代码 代码如下:

<%
Dim username, password
username = Session("username")
if username = "" then
Session 中没有用户登录信息
username = Request.Cookies("username")
password = Request.Cookies("password")
注意上面的两句得到的 username 和 password 要进行 SQL 注入漏洞的防范(即过滤掉单引号“”),这里略去
if username = "" or password = "" then
用户没有登录
...
else
这里假设已经创建了 conn 和 rs 对象
rs.Open "SELECT TOP 1 * FROM [user] WHERE username=" & username & " AND password=" & password & "", conn, 1, 3
if rs.eof then
Cookies 中的信息非法
...
else
Cookies 中的信息合法,自动登录
Session("username") = username
...
end if
end if
else
用户信息已经存在于 Session 中,直接读取
...
end if
%>

js:
复制代码 代码如下:

<%
var username, password;
username = Session("username") + "";
if (username == "" || username == "undefined") {
// Session 中没有用户信息
username = Request.Cookies("username") + "";
password = Request.Cookies("password") + "";
// 注意上面的两句得到的 username 和 password 要进行 SQL 注入漏洞的防范(即过滤掉单引号“”),这里略去
if (username == "" || username == "undefined" || password == "" || password == "undefined") {
// 用户没有登录
...
}
else {
// 这里假设已经创建了 conn 和 rs 对象
rs.Open("SELECT TOP 1 * FROM [user] WHERE username=" + username + " AND password=" + password + "", conn, 1, 3);
if (rs.eof) {
// Cookies 中的信息非法
...
}
else {
// Cookies 中的信息合法,自动登录
Session("username") = username + "";
...
}
}
}
else {
// 用户信息已经存在于 Session 中,直接读取
...
}
%>

但是这种方法对于用户来说又不太安全,原因是浏览器每次访问页面时都会把 Cookies 传输过去,而包含密码的 Cookies 一旦被他人获取将导致用户帐号被盗 。对于这种情况,又出现了第二种方法,即在用户信息数据库中增加一个字段“verifycode”,在用户登录时,随机产生一个长整型校验值存入 verifycode 字段,并且将 username 和这个 verifycode 值而不是 password 存入 Cookies 。而在验证 Cookies 中的用户信息时,也只验证 username 和 verifycode 。这种方法的好处在于,即使用户的 Cookies 被黑客获取,他也只能利用这个“临时”产生的 verifycode 登录,而无法获得用户的密码 。只要此用户再一次使用用户名和密码登录,这个 verifycode 值便会改变,黑客便无法通过原来的 verifycode 登入 。
这种方法的实现只需要在上述方法一的代码上稍加改动 。首先,在您的登录程序中,在验证通过存储用户信息的地方需要加上一段:
vbs:
复制代码 代码如下:

<%
Response.Cookies("verifycode") = int(rnd * 2100000000)
%>

js:
复制代码 代码如下:

<%
Response.Cookies("verifycode") = Math.floor(Math.random() * 2100000000);
%>

然后,在上面提供的验证代码中把对 Cookies("password") 的验证改为对 Cookies("verifycode") 的验证即可 。
四、结论
通过我们的分析以及处理,Cookies 欺骗漏洞已经被完全解决,从此,我们的 ASP 程序变得更加安全了 。