用户登录安全性的简单实例分析(Cookie、加密)
关键字:Cookie;DES加解密算法;安全性;权限;
下面是以前写的一篇文章,不一定会在目前的实际项目中应用,所以仅作为个人的业余读书、业余爱好。
从事hack的朋友可能会经常提到SQL注入、暴库、COOKIE欺骗、跨站提交、端口、服务、脚本漏洞,IIS漏洞(这个和自己写的程序就没关了,是IIS的配置与安全检测问题)、……各式各样的入侵,然而在OS安全性日益成熟的今天,网站形式的入侵成为了hacker们最主要的方式,因为在编码方面不是每一个程序员都能够完全的处理的好,尤其是Web Develop方面的新手(像我这样J),这一点可能会很容易忽视,熟不知安全问题是Web系统的根本……而这些实际上的安全问题个人觉得还是可以避免的,关键是看自己如何来编程,如何去实现,下面我以Cookie使用做事例来简单的说明下:
Cookie的使用是涉及到用户的权限、帐户等敏感信息的,所以一旦你决定使用Cookie来存放用户的登陆或配置信息,你一定要注意对COOKIE的加密等操作了,当然,也不能说这样不安全,那还干吗用它呢,不是这样的,其实既然COOKIE存在自然有它存在的道理,现在的大部分站点,基本上都采用Cookie来存放这些信息小,可见COOKIE还是有它的魅力!
对于Cookie的相关知识,援引一下它的简单介绍:
简介
Cookie 为 Web 应用程序保存用户相关信息提供了一种有用的方法。例如,当用户访问您的站点时,您可以利用 Cookie 保存用户首选项或其他信息,这样,当用户下次再访问您的站点时,应用程序就可以检索以前保存的信息。
Cookie 的限制
在开始讨论 Cookie 的技术细节之前,我想先介绍一下 Cookie 应用的几条限制。大多数浏览器支持最多可达 4096 字节的 Cookie,如果要将为数不多的几个值保存到用户计算机上,这一空间已经足够大,但您不能用一个 Cookie 来保存数据集或其他大量数据。在实际应用中,您可能并不希望在 Cookie 中保存大量的用户信息,而只希望保存用户编号或其他标识符。之后,当用户再次访问您的站点时,您就可以使用该用户 ID 在数据库中查找用户的详细信息。(有关保存用户信息的说明,请参阅 Cookie 和安全性。)
浏览器还限制了您的站点可以在用户计算机上保存的 Cookie 数。大多数浏览器只允许每个站点保存 20 个 Cookie。如果试图保存更多的 Cookie,则最先保存的 Cookie 就会被删除。还有些浏览器会对来自所有站点的 Cookie 总数作出限制,这个限制通常为 300 个。
您最可能遇到的 Cookie 限制是:用户可以设置自己的浏览器,拒绝接受 Cookie。您很难解决这个问题,除非完全不使用 Cookie 而是通过其他机制来保存用户相关信息。保存用户信息的一种常用方法是会话状态,但会话状态又依赖于 Cookie。这一点在后面的 Cookie 和会话状态中
控制 Cookie 有效范围
默认情况下,一个站点的全部 Cookie 都一起保存在客户机上,而且所有这些 Cookie 都会随着对该站点发送的请求一起发送到服务器,也就是说,站点的每个页面都能得到该站点的所有 Cookie。但有时候,您可能希望 Cookie 更具有针对性,这时,您可以通过两种方法设置 Cookie 的有效范围: 把 Cookie的有效范围限制在服务器上的一个文件夹中,实际上这样就将 Cookie 限制到站点上的某个应用程序。
把有效范围设置为某个域,从而允许您指定域中的哪些子域可以访问 Cookie
COOKIE有效期
您可以读取 Cookie 的名称和值,除此以外,需要了解的有关 Cookie 的信息并不是很多。虽然您可以获取 Domain 和 Path 属性,但是这些属性的用途很有限。例如,您可以读取 Domain 属性,但如果您的页面与 Cookie 不在相同的域,您根本就不会在页面的位置接收到该 Cookie。
您无法读取的是 Cookie 的过期日期和时间。事实上,当浏览器向服务器发送 Cookie 信息时,浏览器并未将过期信息包括在内。您可以读取 Expires 属性,但总是返回为零的日期/时间值。Expires 属性的主要作用是帮助浏览器执行有关 Cookie 保存的日常管理。从服务器的角度来看,Cookie 要么存在要么不存在,所以对服务器而言,有效期并不是有用的信息。所以,浏览器在发送 Cookie 时并不提供此信息。如果您需要 Cookie 的过期日期,就必须重新设置,关于这一点我将在修改和删除 Cookie 中介绍。
更确切地说,您可以在向浏览器发送 Cookie 之前读取已在 Response 对象中设置的 Expires 属性,但您无法从返回的 Request 对象中获取有效期信息。
上面是引用的对COOKIE的简单介绍,具体的信息可参考MSDN文档,下面是自身对Cookie信息操作的简要概述:
在使用COOKIE时,也是把用户名和密码存储起来的,不过为了安全起见,是一定要进行加密的,对于如何写入COOKIE和读取COOKIE,我这里不在追述。
写入到COOKIE后,COOKIE文件中存放信息如下:
COOKIE名,字段名=值,字段名=值,字段名=值……
现在不但要对值进行加密,对字段名也要同样进行加密,具体的实现方式略有不同,扩展性也是.
首先加密字段名,这个可以采用DES加密算法,由于字段名必须是在下次登陆时可以正确识别的,不然你将无法得到对应的字段值,也就不可以判断用户的权限,可见在安全性实现方面不是很妥,下面是我参考VB版的DES加密、解密算法用C#实现的(.NET里该还没有封装吧):
1、首先定义字节型存储数组,用于存储编码时的转换处理
private static Byte[] KEY_64
{
get
{
return new byte[]{42, 16, 93, 156, 78, 4, 218, 32};
}
}
private static Byte[] IV_64
{
get
{
return new byte[]{55, 103, 246, 79, 36, 99, 167, 3};
}
}
// #endregion
2、加密实现部分
private static string EncryptCookie( string name) // 标准的DES加密 关键字、数据加密
{
//#region DES加密算法
if(name!="")
{
DESCryptoServiceProvider cryptoProvider=new DESCryptoServiceProvider();
MemoryStream ms=new MemoryStream();
CryptoStream cs=new
CryptoStream(ms,cryptoProvider.CreateEncryptor(KEY_64,IV_64),CryptoStreamMode.Write);
StreamWriter sw=new StreamWriter(cs);
sw.Write(name);
sw.Flush();
cs.FlushFinalBlock();
ms.Flush();
//再转换为一个字符串
return Convert.ToBase64String(ms.GetBuffer(),0,Int32.Parse(ms.Length.ToString()));
}
else
{
return "";
}
//#endregion
}
3、解密实现部分
private static string DecryptCookie( string temp) // 标准的DES解密
{
//#region DES 解密算法
if(temp!="")
{
DESCryptoServiceProvider cryptoProvider=new DESCryptoServiceProvider();
//从字符串转换为字节组
Byte[] buffer=Convert.FromBase64String(temp);
MemoryStream ms=new MemoryStream(buffer);
CryptoStream cs=new
CryptoStream(ms,cryptoProvider.CreateDecryptor(KEY_64,IV_64),CryptoStreamMode.Read);
StreamReader sr=new StreamReader(cs);
return sr.ReadToEnd();
}
else
{
return "";
}
//#endregion
}
根据上面的实现进行编码加密,可以很方便的读取到字段名、字段值,如果字段值同样的采用该加密算法的话,那还是不可取的,因为该加密算法为对称加密形式的,所以复制串后即可得到解密值,那该怎么做呢?其实字段名是否采用该方法就无关紧要了,而不是字段值.(可能还会遇到没法读字段和值的问题那是因为加密后产生了++=等类似的符号,所以还要进行URL编码或其他操作,复杂度越高越好,当然也不是提倡多重……)
看来对于字段值的加密该是主要完成的地方J,其实也可以自己写个加解密算法,那样在不公布代码的情况下,别人也不会轻易识别的,如果想省事的话,那就直接用MD5(.NET封装了MD5算法,很方便使用temppass=FormsAuthentication.HashPasswordForStoringInConfigFile(temppass,"MD5"))吧,可能会很惊讶,用MD5能读取回来吗?当然可以,既然上面的字段名你得到了,那字段值不是也同样的得到了吗,得到该字段值以后,不管是什么类型的加密,你都可以用它和数据库中存储的校验信息进行比对,单说密码,则可以将读取的MD5字段值和数据库中的MD5密码进行对比,当然了,如果你懒得将密码进行MD5加密(一般都会加密的吧),那也可以读取数据库里的密码信息,转换为MD5后和从COOKIE里读到的MD5加密字段值进行比对,……所有的操作只是一个中间的过程,并不会影响原有的数据信息。
同样的方式对COOKIE文件里的其他字段、字段值进行加密,在完成上面的操作后,在下次登陆时判断COOKIE信息的页面别忘记了一定要和数据库中的信息进行比较,在此基础上,可将COOKIE里读取的信息写入Session,其他页面的权限判断就可以采用Session来操作了(对于COOKIE所有的操作都是以COOKIE中读取数据为前提的……), 以上为个人的言论,不代表大多数人的看法!希望大家批评指正。
In addition:
严格的检查权限、参数过滤
不公开源码、DLL封装
加密越复杂越好