由拖库攻击谈Discuz口令字段的加密策略

mark35 发布于 2011/12/31 14:49
阅读 1K+
收藏 3

先转一篇文章:

安全崩盘的年代:由拖库攻击谈口令字段的加密策略

http://www.leiphone.com/no-safe.html

 

节选

编者按:本文作者肖新光,网络ID江海客,安天实验室首席技术架构师,研究方向为反病毒和计算机犯罪取证等。如果有读者想要就安全问题和作者探讨,可以在微博@江海客

我不得不惨痛地写在前面的是,这是一个安全崩盘的时代。过去一年,已经证实的遭遇入侵、并导致关键数据被窃或者被泄露的公司,包括索尼、世嘉这样的大型游戏设备厂商;包括花旗银行这样的金融机构,也包括了RSA这样的安全厂商。

这些事件中最令业界瞠目的是RSA被入侵,这直接导致多家工业巨头遭遇连锁的攻击,很多安全企业本身也使用RSA的令牌。比RSA弱小很多的荷兰电子认证公司DigiNotar已经在被入侵后,宣告破产。

就在2011年上半年,我们还是站在旁观者的立场讨论这些事情。但随即我们就遭遇了CSDN、多玩和天涯等等的数据泄露,其中最为敏感的,一方面是用户信息,另一个当然就是用户口令。由于身份实名、口令通用等情况影响,一时间人人自危。各个站点也陷在口水当中。

但实际上根据推断,这些入侵都是一些过去时,也就是说这些库早就在地下流传。同时流出,也许就是一个集体性的心理效应。

这种针对数据库记录的窃取,被一些攻击者称为“拖库“,于是有了一个自然而谐音的戏称“脱裤”。只是攻击者日趋不厚道,从前只是偷了人家的裤子,现在还要晾在大街上,并贴上布告说,“看,丫裤子上还有补丁呢”。

如果拖库是很难避免的,那么采用合理的加密策略,让攻击者拿到库后的影响降低到更小就是必要的。

明文存放口令的时代肯定是要结束了,但加密就安全么?

那些错误的加密策略

明文的密码固然是不能接受的,但错误的加密策略同样很糟糕。让我们看看下列情况。

简单使用标准HASH

我想起了一个90年代黑客笑话,有人进入一台UNIX主机,抓到了一个shadow文档,但破解不了。于是,他用自己的机器做了一个假的现场,故意 留下这个shadow,最后看看别人用什么口令来试,最后再用这些口令与渗透原来的主机。遗憾的是,那时我们都把这个当成一个Joke,充其量回复一句 “I服了you!“,而没有反思使用标准算法的问题。

目前来看,在口令保存上,使用最为广泛的算法是标准MD5 HASH。但实际上,很长时间,我们都忽略了HASH设计的初衷并不是用来加密,而是用来验证。系统设计者是因为HASH算法具有不可逆的特点所以“借” 用其保存密码的。但其不可逆的前提假设,是明文集合是无限大的。但放到口令并不一样,口令的长度是受限的,同时其可使用的字符也是受限的。我们可以把口令 的总数看正一个事实上的有限集(很难想象有人用100个字符作为口令)。

比如一个人的密码是“123456”,那么任何采用标准MD5加密的网站数据库中,其存放的都是这样一个MD5值:E10ADC3949BA59ABBE56E057F20F883E

由于密文均相同,加之HASH算法是单向的,因此攻击者较早使用的方法就是“密文比对+高频统计“后生成密文字典来攻击,由于绝大多数网站和系统的 加密实现,都是相同明文口令生成相同的密文,因此,那些有高频密文的用户就可能是使用高频明文口令的用户。攻击者一方面可以针对标准算法来制定高频明文的 对应密文档来查询,另一方面,对于那些非标准算法,高频统计攻击的方法也非常常见。

但查表攻击迅速压倒高频统计的原因,正是从2000年开始陆续有网站规模性明文口令泄漏事件开始的。在过去每一次明文的密码泄漏事件,攻击者都会把使用MD5、SHA1等常见HASH算法加工成的口令与那些采用HASH值来保存的库进行应对。

随着超算资源的廉价、GPU的普及、存储能力的增长,一个不容忽视的威胁开始跃上桌面,那就是,这些巨大的HASH表已经不仅仅是基于泄漏的密码和 常见字符串字典来制作,很多攻击者通过长期的分工协作,通过穷举的方式来制作一定位数以下的数字字母组合的口令串与多种算法加密结果的映射结果集,这些结 果集从百GB到几十TB,这就是传说中的彩虹表。

HASH的单向性优势在此已经只有理论意义,因为HASH的单向性是靠算法设计保证的,使用一个有限集来表示一个无限集,其必然是不可逆的。但攻击者是从查表来完成从HASH到口令明文的还原的。因此其算法的单向性也就失去了意义。

联合使用HASH

一些人误以为,HASH不够安全是因为HASH算法的强度问题,因此把MD5或者SHA1联合使用,其实这是毫无价值的(只是徒耗了存储资源)。如 上面所说,HASH的不安全性在于大量口令与其HASH值的对应关系早已经被制作成彩虹表。只要你联合使用HASH的算法其中之一在彩虹表中,自然就可以 查到了。

同理,那种采用“MD5的头+SHA的尾“之类的,或者采用其他的混合两个值的方法,也一样是没有意义的。因为攻击者可以很容易的观察到这种组合方法的规律,经过拆解后继续按照查表法破解。

 

 






 

Discuz7采用的加密方式为md5, md5(md5(password). salt) 值以及salt入库。用户登录时对明文口令先做md5然后提交,后台把提交过来的hash值与该用户数据库保存的salt字符串拼接后再次做md5,然后 与数据库中的password值进行对比。

DZ的加盐字符串是6位字符,基本安全。但现在跑字典的越来越厉害,已经有专门针对DZ这种加密方式(准确说是散列方式)进行爆破(包括字典查询) 的攻击方式。比如 http://www.cmd5.com/Default.aspx 网站就可选多种论坛软件加密方式字典查询。

 

虽然md5、sha1等摘要算法是不可逆的或者说是有损的,但考虑到用户口令长度有限,论坛上使用的一般不会超过20个字符。那么即使摘要算法不可逆,但此映射却基本是一一对应的——只要被拖到库,依据口令密文和salt值就可以[b]还原[/b]出你的明文口令。

 

要想避免这种情况那么就需要在对口令处理上进行其他有损 处理:

 

// Discuz默认口令入库处理方式
$passwd = md5( md5($passwd). $salt);

// 有损处理的口令入库方式:
$passwd = substr(sha1(md5($passwd). $salt), 0, 32) ;

 

改进的方式使用sha1算法主要目的并不是增加算法难度而是产生大于md5算法长度(32位)的字符串(40位)用于截取出标准md5长度字符串从 而实现有损处理。这样处理的结果使得即使获得入库口令以及salt值也无法还原出用户原始明文口令,当然可以通过碰撞实现找到“可以通过登录验证的口 令”,但用户原始口令安全性大大提高。

 

这种方式优点是sha1处理仅限于后台PHP流程中,不需要修改前台代码。

缺点是因为入库口令摘要方式变化,已经保存的口令将无法用于新方式验证,必须对 uc_client/control/user.php中 onlogin()函数做修改判断是否需要做DZ默认认证。 一个办法是数据库保存老的password及salt值,通过验证后写入新算法的值然后删除老的password及salt。

 

对加密、摘要算法不熟悉,不确定这种方式能否有效抵御字典攻击~

以下是话题补充:

@mark35:这种方式目的不是避免通过碰撞找出可以通过验证的明文口令,而是基本保证即使被拖库也不会泄漏用户原始明文口令。通过碰撞找出的口令也仅能在这个站点登录,除非某个站点也采用同样的有损算法。 (2011/12/31 20:02)
加载中
1
乌龟壳
乌龟壳

Django的加密算法曾让我眼前一亮,分享给诸位看官看看。

数据库里保存的模式是

附加字符串|哈希算法|哈希后的值

附加字符串每次修改密码的时候都会随机生成,哈希算法在MD5/SHA等之间随机生成,生成的时候将附加字符串拼上密码,再用哈希算法运算后保存在最后一个部分,这样就很难反查询到了(除非密码太简单,在常用字典里,暴力破解就可以了。)

0
虫虫
虫虫
所有这种方法的前提是,攻击者没有拿到源代码~ 拿到源码这些手段都无效,哈哈
0
虫虫
虫虫
痛苦的是 Discuz 的源代码是开放的,所以这中加密和简单的 md5+salt 无区别
0
拼了命装可爱
拼了命装可爱
楼上可以尝试逆向破解一个 substr(sha1(md5($passwd). $salt), 0, 32)过的密码。关键是这种有损方式后面8位已经被切掉了。
0
我土鳖

关键是拖库和爆后台之间的关系

如果拖库者可以弄到源码,自然没安全性

但是如果不能获取源码,安全性可以被保密所增强

放牛娃1988
放牛娃1988
@mark35 : 他说的加密算法是论坛对密码的加密过程,而不是基础hash加密过程,比如MD5,SHA1之类
mark35
mark35
所有健壮的加密算法代码都是公开的,或者依靠私密算法实现的加密的可靠性都值得怀疑。
0
放牛娃1988
放牛娃1988

引用来自“拼了命装可爱”的答案

楼上可以尝试逆向破解一个 substr(sha1(md5($passwd). $salt), 0, 32)过的密码。关键是这种有损方式后面8位已经被切掉了。
我一开始跟你想的一样,但是我现在怀疑这有没有作用。一个是40位的SHA1,一个是40位SHA1的MD5的前32位,看似后面的进行了有损,但是依然可以列举32位结果加上后8位任意值的原密码。原来的40位密码可能会有碰撞,后面的前32位子串也可能会有碰撞,但是真的碰撞几率就提高很多吗?要知道,32位的hash集太大了,只要是常见密码,在黑客的彩虹库里,查询32位结果+8位任意串的库,可能还是只有一个。不知道我的意思说清楚了没有,这种有损处理在加密过程被破解的情况下,只是增加了碰撞几率,可能会保护原密码不被泄露,但是前32位碰撞的几率,我真的不知道有多高。因为原来的密码用的是32位md5进行加密的,如果这个不安全,也就是碰撞几率不高,那么后面的碰撞几率也不会高,所以,我认为这个过程不会保护原密码,不知道大家以为如何?
mark35
mark35
其实没有增加也没减少碰撞机率,因为最后结果也是32位字符串
0
放牛娃1988
放牛娃1988
我是一个新手,对加密几乎没什么了解,所以我说的话可能是严重错误的。凭我有限的技术能力,我认为原文作者可能只是为了增加加密复杂度,以此防止discuz的公开机密过程对所有采用discuz网站造成危害。但是,如果你认为这个加密过程在被破解的情况下,依旧可以保护原密码不被泄露,那我觉得是不客观的。因为32位子串发生碰撞的几率和32位MD5发生碰撞的几率是一样高的,如果通过32位MD5能反向得到结果,也就是32位MD5在彩虹库中没有发生碰撞,那么同样的,反向32位加密结果+8位任意匹配字符得到的结果也应该只有一个,也就是没有碰撞,因此,这并没有提高碰撞几率,也就没有降低原密码泄露危险。
放牛娃1988
放牛娃1988
@mark35 : 没有提高碰撞几率,那如果知道一个可以产生同样加密结果的密码,不就确定了其本身密码是多少吗?怎么叫保护密码不被泄露?
mark35
mark35
请见我在上面主题贴的补充说明
0
放牛娃1988
放牛娃1988

看来楼主还是没能理解我的意思啊,那我再来解释一下。

如果一个黑客获得了一个32位MD5的加密结果,那么,原密码会是多少?结论是有无穷多个,这是由于MD5的无穷输入导致有穷输出的加密性质决定的。我们假定一个拥有所有密码可能的超强大的彩虹库,那么,通过彩虹库查询到的原密码通常只有一个,因为在有限的密码集上,碰撞几率极低,这样就泄露了原密码。当然,如果发生碰撞了,那黑客是不知道原密码的,虽然破解了登陆过程,但是不会泄露真实密码,我们假定会发生碰撞的几率是q,那么这种加密方法能有效保护原密码的几率是q。

那么再看另外一种加密方法,40位的SHA1密码,取32位作为加密结果。这样的加密过程看似进行了有损,但事实上,我们如果在上面定义的彩虹库上查找以加密结果为前32位结果的所有原密码,虽然查找结果进行了扩大,但是hash算法的散列特征,我们可以认定,其碰撞几率依旧是q,因为都是32位散列。所以,这样的查询结果依旧只有q的几率发生碰撞,那么也就只有q的几率的密码会保护。

因此看来,这两种加密方法保护密码的能力在破解了加密过程和密码库,同时拥有同等强大的彩虹库下的表现是完全一致的。请楼主好好思索我说的话,目前你还是没能解答我的疑惑。谢谢。

mark35
mark35
2012快了,等我慢慢消化~
0
放牛娃1988
放牛娃1988
当然了,我是从比较业余的角度来想这个问题的,原文作者是这方面的专家,很大可能是我有什么地方理解错了,所以我是想知道我错在什么地方。如果说错了,希望大家不要见笑,也希望大家不要被我的说法给误导了。
0
我土鳖
可以在使用公共算法的基础上加入若干私密环节(进行简单的换位/置换/异或),安全性本身不成问题(依赖于所使用的公共算法)
返回顶部
顶部