一直以来很多程序员在网站制作的过程中喜欢使用MD5对用户的密码进行加密保存,比较细心的程序员还会对用户的密码保护答案进行MD5加密,这样可以最大限度的保护用户的隐私。对于很多网站保存用户密码保护问题及答案的做法这里提出批评:
你们是否考虑过用户的隐私?是否考虑过一旦密码保护的答案被一些不坏好意的人知道以后可能导致的一连串安全问题?
例如——现在很流行的社会工程学入侵,简单的可以理解为3部分:
踩点——通过搜集目标用户或者网站管理员的习惯、资料获得最大程度的信息
猜测、欺骗——与目标用户或网站管理员套近乎,尽量骗取对方信任,从而了解对方的习惯、兴趣爱好,在信任度达到一定程度的时候可以骗取对方点击一些包含恶意代码的网站、或着发送包含恶意代码的文件甚至是可执行文件(最好是有0day),那样就事半功倍了!
如果通过上面的手段未能得到对方信任、或者没能得到对方
电脑权限。那么就开始整理前面搜集来的以及通过“套近乎”得到的有用信息,从中得到对方例如:生日、家庭地址、家庭电话、工作单位、手机、爱人姓名、爱人生日……从中就有很大把握得到对方密码,这个就是个人习惯导致的,关于这个问题将在以后的文章中单独详细说明!
言归正传,或许你会问这些和我们保存明文资料有什么关系?
告诉你,很有关系!因为我们前面说到的资料有一种获取途径就是从目标用户经常上的一些网站上获取来的!
假设:目标用户毕业于某XXX大学,因此他经常上这个大学的校友论坛进行联谊或者其他交流。那么他在这个论坛必定需要注册,论坛注册通常需要填写:
用户名
密码
邮箱
密码保护问题
密码保护答案
有的甚至要求你填写生日资料,当然这个通常是在详细资料里备选的。不过在类似校友论坛这样的地方大家都会很乐意填写真实资料(此外,如果找到目标用户的QQ那么在腾讯的QQ空间上也能轻松的找到你的生日!因为腾讯注册时候是需要填写生日作为密码保护及身份验证的资料,此外每当一个用户生日。所有用户都会收到官方的提示:您的好友XXX生日就要到了,您可以发送祝福……那么我们就顺利得到生日)
前面我们已经说道,得到这些资料就有很大把握能得到密码。所以如果你是一个普通用户,你经常上网,到处注册,那么就要小心保护你的个人隐私了。尽量不要使用相同的密码,更不要使用简单密码!因为很多用户为了图好记忆、或者方便。经常使用一些简单的密码。而且几乎所有地方的密码都是同一个,这个时候如果你所注册的网站存在安全问题,那么你的资料就轻易的被人得到了。
所以接下来要说的是关于程序编写者及网站运营商:
希望你们能在程序编写过程中对用户的资料进行绝对加密,我这里的意思是你们可以写一套独立的加密机制,对用户资料和密码加密,当然如果不是一些大型公司,是没有专业的人员可以写出像——MD5、RSA这样让别人直接无法破解的密码。所以普通用户就听听我下面的建议和构思吧!
对用户的所有资料包括:用户名、密码、生日、密码保护问题及答案等全部进行MD5加密,这样做不但能保护用户的隐私,也能大大提高资料的保护和安全性!
当然,简单的MD5加密是没有办法达到绝对的安全的。因为普通的MD5加密是允许被查询的。接下来的重点就是如题目所说。对MD5进行改造、增强!
下面是我的思路:
对MD5密码进行截取保存及截取验证
一个简单的例子
A=”123456”
Response.write (md5(A))
得到的结果是:
16位:49ba59abbe56e057
32位:e10adc3949ba59abbe56e057f20f883e
如果直接这样保存进数据库。当网站存在注入。或者其他什么漏洞,导致这段密文被人知道,那么就可以查询或者爆破得到密码。
那么我们要做的是,将密码进行随机截取,比如我截取验证前面14位
Rs(“password”)=left(md5(a),14)
这样就把MD5密码的前14位写进数据库。
然后验证的使用使用
If left(request.form(“a”) ,14)<>rs(“password”) then
Response.write (“密码错误”)
Else
Response.write (“登陆成功”)
End if
那么得到一个14的MD5你郁闷不郁闷?
想破解?破解去吧!后面差了2位的可能组合有多少,就不用我去算了吧?
或许你会问。这么以来后面也就是只要前面14位一样就可以成功了?那么不是同样加大了密码被暴力破解出来的可能性吗?因为只要满足前14位相同就可以登陆成功啊!
也就是说加入后面2位带来的组合有1000种。那么就是说我只要破解出这1000种组合里的1个就能成功登陆了。
是的!没错,如果只是这样做,虽然是密码复杂性加大,但是也导致密码更容易被破解,那么如何解决这个问题?
我想了很久,终于有了点头绪.那就是——让用户自定义截取的长度,及截取的位置、对加密长度再进行自定义组合。那么在网站没被攻陷之前,你是没有办法的得知密码的解密及截取组合方式的。想要按照上面说的按照列出可能的所有组合然后再进行爆破得到一个就得到权限,就不可能了。因为按照我上面的办法组合出来的密码的可能组合数是不可测的,全部列举出来都够你去自己建立一个cmd5.com的数据库了。所以攻击者只能放弃对md5密码的猜解。那么及时我给你密文。给你后台地址。你也永远进不去。永远得不到权限了。
光说不做没有意义,接下来就讲讲具体的实现办法:下面粗糙的写了几个简单例子,具体应用看各位程序员自己灵活运用思路了
先定义几个变量:
password1(客户端提交的密码)
password2(服务端数据库内的密码)
beginnumber (开始截取的位置)
number (截取位数)
首先是注册页面,用户提交的所有资料都进行md5加密,关键部分例如:密码则使用下面的混淆加密,或者索性全部使用下面的混淆加密方式好了
首先申明:截取的部分是要被丢弃的部分,丢弃的部分需要用其他字符串来填充(如果你喜欢直接用截取的,就不必要使用填充了),下面是填充部分的随机数函数
用来随机生成由0-9及a-z的组合,你也可以自己修改成带大写字母的
Function gen_key(digits)
'定义并初始化数组
dim char_array(80)
'初始化数字
For i = 0 To 9
char_array(i) = CStr(i)
Next
'初始化小写字母
For i = 36 To 61
char_array(i) = Chr(i + 61)
Next
Randomize '初始化随机数生成器。
do while len(output) < digits
num = char_array(Int((62 - 0 + 1) * Rnd + 0))
output = output + num
loop
'设置返回值
gen_key = output
End Function
'把结果返回给浏览器
下面是注册页面写入数据库的处理部分
Oldpassword= md5(request.form(“password1”))
…..读取数据库部分省略
A=left(Oldpassword,beginnumber-1) ‘截取客户端得到的密码原始md5值未被截取的前端部分
B=right(Oldpassword,16-(beginnumber+number-1)) ‘截取客户端得到的密码原始md5值未被截取的后端部分
Password1=A&get_key(number)&B ‘截取部分调用随机函数随机生成一组数并且与前面截取的前端及后端重新组合在一起
Rs(“password2”)=password1 ’将组合后的密码存入数据库
这样以来你得到的就是一组16位没有人知道的是什么的变形MD5了,及时得到密文也无法正确破解
那么保存成功,接下来如何读取和验证呢?同样给出一个简单的例子:
funcition pass_left(pass) ‘首先定义截取md5密码左端部分的函数
pass=left(pass,beginnumber-1)
Changepass=pass
End function
funcition pass_right(pass)’定义截取md5密码右端的部分
pass=left(pass, 16-(beginnumber+number-1))
Changepass=pass
End function
Password=md5(request.form(“password”)) ‘获取客户端密码
…读取数据库部分
…..
If pass_left(password)<>pass_left(rs(“pasword2”)) or pass_right(password)<>pass_right(rs(“password2”)) then ‘对随机截取部分外的部分进行比对判断
Response.write “密码错误”
Else
Response.write “登陆成功”
End if
到这里就完成了对md5的随机加密增强。从此md5的安全性又上了一层台阶!
经过这样混淆加密的密文复杂度和可能种类多了非常多,而且也容易欺骗入侵者,即使他们查询到了。也登陆不进去,思维一定很混乱或许会认为这是一个虚假的数据库。或者蜜罐,从而放弃攻击和猜解.