Cookies欺骗分析与防御

今天来谈谈cookies欺骗是怎么回事以及如何避免。html

用户在登陆以后一般会保存用户信息,以便在其余须要权限的页面去验证用户信息是否具备访问权限。web

有同窗说我在登陆的时候已经很注意SQL注入问题了,还有什么不安全的地方么?数据库

固然有!这个要首先谈一个问题,那就是用户身份验证的流程 以下图:浏览器

 

所以咱们能够看出,一个页面是否可以被访问,判断依据是经过存储信息区域中用户的信息来判断的安全

而登陆页面的做用就是 验证 用户输入的用户名+密码的组合是否在数据库中存在,若是存在则把信息保存在存储信息的区域,以便各个页面去判断权限服务器

OK,理清这个思路以后咱们的重点就来了,那个信息存储区域对于咱们来讲相当重要,通常常见的有两种形式,session和cookiescookie

 

session和cookies一样都是针对单独用户的变量(或者说是对象好像更合适点),不一样的用户在访问网站的时候 都会拥有各自的session或者cookies,不一样用户之间互不干扰。session

他们的不一样点是:工具

1,存储位置不一样性能

session在服务器端产生,比较安全,可是若是session较多则会影响性能

cookies在客户端产生,安全性稍弱

2,生命周期不一样

session生命周期 在指定的时间(如20分钟)到了以后会结束,不到指定的时间,也会随着浏览器进程的结束而结束。

cookies默认状况下也随着浏览器进程结束而结束,但若是手动指定时间,则不受浏览器进程结束的影响。 

 

因为若是用户信息使用session保存的话,用户信息每每会丢失而须要从新登陆,使用cookies的话则能够长时间有效比较利于用户体验,那session的状况咱们不讨论,下面说说使用cookies保存用户信息的状况。

 

咱们首先建立两个页面分别是Login.aspx和Main.aspx。Login.aspx用于获取并保存用户信息到cookies中,Main.aspx则用户验证用户是否有权访问本页面,咱们在本例中设定,登陆用户有权访问,匿名(未登陆)用户,拒绝访问。

首先来看Login.aspx 咱们先建立两个按钮

“获取登陆状态”按钮会 把信息保存到cookies中,这里仅保存UID,而后重定向到Main.aspx

“未获取登陆状态”按钮 直接重定向到Main.aspx 进行匿名访问

 

Login.aspx.cs 程序代码:

 1     protected void Page_Load(object sender, EventArgs e)
 2     {
 3         //每次加载登陆页面 清理UID 清除登陆状态
 4         Response.Cookies["uid"].Value = "0";
 5     }
 6     protected void Button1_Click(object sender, EventArgs e)
 7     {
 8         //验证步骤略过,假设用户经过验证而且获得以下信息:
 9 
10         int uid = 1; //用户惟一ID
11         string username = "admin"; //用户名
12         string userpwd = "123456"; //用户密码
13 
14         //接下来要保存用户登陆状态
15         Response.Cookies["uid"].Value = uid.ToString();
16 
17         //跳转到登陆后的页面
18         Response.Redirect("Main.aspx");
19 
20     }
21     protected void Button2_Click(object sender, EventArgs e)
22     {
23         //未经验证直接进入Main.aspx
24         Response.Redirect("Main.aspx");
25     }

 

在Main.aspx中进行验证用户是否已经登陆

 

 1     protected void Page_Load(object sender, EventArgs e)
 2     {
 3         CheckLogin();
 4     }
 5 
 6 
 7     private void CheckLogin()
 8     {
 9         if (Request.Cookies["uid"] != null && GetUserInfo(int.Parse(Request.Cookies["uid"].Value), "") != "")
10         {
11             Response.Write(GetUserInfo(int.Parse(Request.Cookies["uid"].Value), "username") + "已登陆");
12         }
13         else
14         {
15             Response.Write("您还没有登录,<a href='login.aspx'>点此登陆</a>");
16         }
17     }
18 
19 
20     /// <summary>
21     /// 模拟一个获取用户信息的方法
22     /// 然而实际操做中须要经过ID查询数据库来获取用户信息
23     /// 这里为了方便演示就直接return固定的值了
24     /// </summary>
25     /// <param name="uid"></param>
26     /// <param name="key"></param>
27     /// <returns></returns>
28     private string GetUserInfo(int uid, string key)
29     {
30         if (uid == 1) //这里只设置uid为1的用户,其余的UID的用户不存在
31         {
32             switch (key)
33             {
34                 case "username": return "admin";
35                 case "password": return "123456";
36                 default: return "null";
37             }
38         }
39         else
40         {
41             return "";
42         }
43     }

 

 OK,咱们来测试一下,点击获取登陆状态,实际上至关于用admin,123456这个组合来登陆。

好的,登陆成功,咱们再来测试下匿名登陆,点击未获取登陆状态

 

事情好像比咱们想象的要顺利,目前来讲咱们想要的效果已经都实现了,可是事实上真的是这样吗,显然不是!

咱们刚才说过,cookies是在客户端产生,也就是咱们本身的电脑上保存的

另外一方面,Main.aspx这个页面判断 你是否可以访问的依据就是 cookies中的值是多少,若是是1,则认为你当前身份是UID为1的用户,若是是5,则认为你当前身份是UID为5的用户。

那么咱们考虑一个事情,若是把个人cookies中的UID修改掉,好比改为35,是否是能够直接绕过登陆页面,就能够以UID为35的用户身份登陆呢?

事实上确实是这样,这也就是标题中所说的cookies欺骗。因为cookies是客户端产生咱们能够很容易的修改,所以产生安全隐患。

下面就来实际测试一下,首先下载一款软件 老兵cookies欺骗工具 界面以下图:

 

在Address中输入咱们项目的访问地址,而后链接

 

而后正常操做一遍,分别点击 获取登陆状态  和  未获取登陆状态

   

发现咱们正常操做是正常的判断,下面重点来了,咱们要修改cookies值 点击未获取登陆状态 同样能够被受权访问

 

 

 

登陆成功了,那么咱们应该如何避免这样的问题呢?

正确的作法是,把密码同时存入cookies(固然实际操做时候须要MD5加密保存,这里为了方面演示使用明文保存),而后在Main.aspx验证时候,同时验证UID和密码是否匹配便可。

咱们来修改一下代码:

Login页面

 1 protected void Page_Load(object sender, EventArgs e)
 2     {
 3         //每次加载登陆页面 清理UID 清除登陆状态
 4         Response.Cookies["uid"].Value = "0";
 5         Response.Cookies["pwd"].Value = "";
 6     }
 7     protected void Button1_Click(object sender, EventArgs e)
 8     {
 9         //验证步骤略过,假设用户经过验证而且获得以下信息:
10 
11         int uid = 1; //用户惟一ID
12         string username = "admin"; //用户名
13         string userpwd = "123456"; //用户密码
14 
15         //接下来要保存用户登陆状态
16         Response.Cookies["uid"].Value = uid.ToString();
17         Response.Cookies["pwd"].Value = userpwd;
18         //跳转到登陆后的页面
19         Response.Redirect("Main.aspx");
20 
21     }
22     protected void Button2_Click(object sender, EventArgs e)
23     {
24         //未经验证直接进入Main.aspx
25         Response.Redirect("Main.aspx");
26     }

 

Main页面

 1 private void CheckLogin()
 2     {
 3         if (Request.Cookies["uid"] != null && Request.Cookies["pwd"] != null && GetUserInfo(int.Parse(Request.Cookies["uid"].Value), "") != "")
 4         {
 5             if (Request.Cookies["pwd"].Value == GetUserInfo(int.Parse(Request.Cookies["uid"].Value), "password"))
 6             {
 7                 Response.Write(GetUserInfo(int.Parse(Request.Cookies["uid"].Value), "username") + "已登陆");
 8             }
 9             else
10             {
11                 Response.Write("您还没有登录,<a href='login.aspx'>点此登陆</a>");
12             }
13         }
14         else
15         {
16             Response.Write("您还没有登录,<a href='login.aspx'>点此登陆</a>");
17         }
18     }

 

这样改动以后,用户若是再以修改cookies企图绕过验证的话,那么他除了修改UID以外,还必须修改pwd为正确的密码。

有同窗问:那若是他就是把PWD改为正确的密码了呢?

这位同窗...你的密码都别别人窃取了...那么再安全的程序代码也救不了你....

 

本文中案例源码及相关工具下载:http://files.cnblogs.com/webconfig/Cookies%E6%AC%BA%E9%AA%97.rar

 

感谢小伙伴们的热烈讨论,按照 @老牛吃肉 和其余同类观点的用户的建议,我尝试作了另外一方案,作下补充。

使用DES把UID加密放在cookies中,在验证阶段解密验证。

http://www.cnblogs.com/webconfig/p/3624831.html

 

 

本文出自 低调码农的笔记簿 http://www.cnblogs.com/webconfig/p/3623343.html 转载请注明出处,若有谬误不当之处,欢迎指正拍砖,不胜感谢!!

相关文章
相关标签/搜索