被脱裤也不怕,密码安全可以这样保障【转】

在前一篇文章《设计安全的账号系统的正确姿势》中,主要提出了一些设计的方法和思路,并没有给出一个更加具体的,可以实施的安全加密方案。经过我仔细的思考并了解了目前一些方案后,我设计了一个自认为还比较安全的安全加密方案。本文主要就是讲述这个方案,非常欢迎和期待有读者一起来讨论。

首先,我们明确一下安全加密方案的终极目标:

即使在数据被拖库,代码被泄露,请求被劫持的情况下,也能保障用户的密码不被泄露。

说具体一些,我们理想中的绝对安全的系统大概是这样的:

  1. 首先保障数据很难被拖库。
  2. 即使数据被拖库,攻击者也无法从中破解出用户的密码。
  3. 即使数据被拖库,攻击者也无法伪造登录请求通过验证。
  4. 即使数据被拖库,攻击者劫持了用户的请求数据,也无法破解出用户的密码。

如何保障数据不被拖库,这里就不展开讲了。首先我们来说说密码加密。现在应该很少系统会直接保存用户的密码了吧,至少也是会计算密码的 md5 后保存。md5 这种不可逆的加密方法理论上已经很安全了,但是随着彩虹表的出现,使得大量长度不够的密码可以直接从彩虹表里反推出来。

所以,只对密码进行 md5 加密是肯定不够的。聪明的程序员想出了个办法,即使用户的密码很短,只要我在他的短密码后面加上一段很长的字符,再计算 md5 ,那反推出原始密码就变得非常困难了。加上的这段长字符,我们称为盐(Salt),通过这种方式加密的结果,我们称为 加盐 Hash 。比如:

salt

上一篇我们讲过,常用的哈希函数中,SHA-256、SHA-512 会比 md5 更安全,更难破解,出于更高安全性的考虑,我的这个方案中,会使用 SHA-512 代替 md5 。

salt

通过上面的加盐哈希运算,即使攻击者拿到了最终结果,也很难反推出原始的密码。不能反推,但可以正着推,假设攻击者将 salt 值也拿到了,那么他可以枚举遍历所有 6 位数的简单密码,加盐哈希,计算出一个结果对照表,从而破解出简单的密码。这就是通常所说的暴力破解。

为了应对暴力破解,我使用了加盐的慢哈希。慢哈希是指执行这个哈希函数非常慢,这样暴力破解需要枚举遍历所有可能结果时,就需要花上非常非常长的时间。比如:bcrypt 就是这样一个慢哈希函数:

bcrypt

通过调整 cost 参数,可以调整该函数慢到什么程度。假设让 bcrypt 计算一次需要 0.5 秒,遍历 6 位的简单密码,需要的时间为:((26 * 2 + 10)^6) / 2 秒,约 900 年。

好了,有了上面的基础,来看看我的最终解决方案:

password_secutity

上图里有很多细节,我分阶段来讲:

1. 协商密钥

基于非对称加密的密钥协商算法,可以在通信内容完全被公开的情况下,双方协商出一个只有双方才知道的密钥,然后使用该密钥进行对称加密传输数据。比如图中所用的 ECDH 密钥协商。

2. 请求 Salt

双方协商出一个密钥 SharedKey 之后,就可以使用 SharedKey 作为 AES 对称加密的密钥进行通信,客户端传给服务端自己的公钥 A ,以及加密了的用户ID(uid)。服务端从数据库中查找到该 uid 对于的 Salt1 和 Salt2 ,然后再加密返回给客户端。

注意,服务端保存的 Salt1 和 Salt2 最好和用户数据分开存储,存到其他服务器的数据库里,这样即使被 SQL 注入,想要获得 Salt1 和 Salt2 也会非常困难。

3. 验证密码

这是最重要的一步了。客户端拿到 Salt1 和 Salt2 之后,可以计算出两个加盐哈希:

SaltHash1 = bcrypt(SHA512(password), uid + salt1, 10)
SaltHash2 = SHA512(SaltHash1 + uid + salt2)

使用 SaltHash2 做为 AES 密钥,加密包括 uid,time,SaltHash1,RandKey 等内容传输给服务端:

Ticket = AES(SaltHash2, uid + time + SaltHash1 + RandKey)
AES(SharedKey, Ticket)

服务端使用 SharedKey 解密出 Ticket 之后,再从数据库中找到该 uid 对应的 SaltHash2 ,解密 Ticket ,得到 SaltHash1 ,使用 SaltHash1 重新计算 SaltHash2 看是否和数据库中的 SaltHash2 一致,从而验证密码是否正确。

校验两个哈希值是否相等时,使用时间恒定的比较函数,防止试探性攻击。

time 用于记录数据包发送的时间,用来防止录制回放攻击。

4. 加密传输

密码验证通过后,服务端生成一个随机的临时密钥 TempKey(使用安全的随机函数),并使用 RandKey 做为密钥,传输给客户端。之后双方的数据交互都通过 TempKey 作为 AES 密钥进行加密。

假设被拖库了

以上就是整个加密传输、存储的全过程。我们来假设几种攻击场景:

  1. 假设数据被拖库了,密码会泄露吗?

    数据库中的 Salt1 ,Salt2 , SaltHash2 暴露了,想从 SaltHash2 直接反解出原始密码几乎是不可能的事情。

  2. 假设数据被拖库了,攻击者能不能伪造登录请求通过验证?

    攻击者在生成 Ticket 时,需要 SaltHash1 ,但由于并不知道密码,所以无法计算出 SaltHash1 ,又无法从 SaltHash2 反推 SaltHash1 ,所以无法伪造登录请求通过验证。

  3. 假设数据被拖库了,攻击者使用中间人攻击,劫持了用户的请求,密码会被泄露吗?

    中间人拥有真实服务器所有的数据,仿冒了真实的 Server ,因此,他可以解密出 Ticket 中的 SaltHash1 ,但是 SaltHash1 是无法解密出原始密码的。所以,密码也不会被泄露。

    但是,中间人攻击可以获取到最后的 TempKey ,从而能监听后续的所有通信过程。这是很难解决的问题,因为在服务端所有东西都暴露的情况下,中间人假设可以劫持用户数据,仿冒真实 Server , 是很难和真实的 Server 区分开的。解决的方法也许只有防止被中间人攻击,保证 Server 的公钥在客户端不被篡改。

    假设攻击已经进展到了这样的程度,还有办法补救吗?有。由于攻击者只能监听用户的登录过程,并不知道真实的密码。所以,只需要在服务端对 Salt2 进行升级,即可生成新的 SaltHash2 ,从而让攻击者所有攻击失效。

    具体是这样的:用户正常的登录,服务端验证通过后,生成新的 Salt2 ,然后根据传过来的 SaltHash1 重新计算了 SaltHash2 存入数据库。下次用户再次登录时,获取到的是新的 Salt2 ,密码没有变,同样能登录,攻击者之前拖库的那份数据也失效了。

Q & A

  1. 使用 bcrypt 慢哈希函数,服务端应对大量的用户登录请求,性能承受的了吗?

    该方案中,细心一点会注意到, bcrypt 只是在客户端进行运算的,服务端是直接拿到客户端运算好的结果( SaltHash1 )后 SHA-512 计算结果进行验证的。所以,把性能压力分摊到了各个客户端。

  2. 为什么要使用两个 Salt 值?

    使用两个 Salt 值,是为了防止拖库后,劫持了用户请求后将密码破解出来。只有拥有密码的用户,才能用第一个 Salt 值计算出 SaltHash1 ,并且不能反推回原始密码。第二个 Salt 值可以加大被拖库后直接解密出 SaltHash1 的难度。

  3. 为什么要动态请求 Salt1 和 Salt2 ?

    Salt 值直接写在客户端肯定不好,而且写死了要修改还得升级客户端。动态请求 Salt 值,还可以实现不升级客户端的情况下,对密码进行动态升级:服务端可定期更换 Salt2 ,重新计算 SaltHash2 ,让攻击者即使拖了一次数据也很快处于失效状态。

  4. 数据库都已经全被拖走了,密码不泄露还有什么意义呢?

    其实是有意义的,正如刚刚提到的升级 Salt2 的补救方案,用户可以在完全不知情的情况下,不需要修改密码就升级了账号体系。同时,保护好用户的密码,不被攻击者拿去撞别家网站的库,也是一份责任。

欢迎大家针对本文的方案进行讨论,如有不实或者考虑不周的地方,请尽情指出。或者有更好的建议或意见,欢迎交流!

文/CoderZh(简书作者)
原文链接:http://www.jianshu.com/p/d3f5aab48158
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

时间: 2024-12-08 23:11:45

被脱裤也不怕,密码安全可以这样保障【转】的相关文章

PHP wget 增强脱裤脚本(PDO MYSQL)

脚本参考了 LCX Gavin2位前辈的帖子.在此表示非常的感谢. https://www.t00ls.net/thread-26740-1-1.html https://www.t00ls.net/thread-26791-1-1.html 说明:脚本支持PDO和MYSQL 2种方式 优先使用PDO .如果服务器不支持PDO  就选择MYSQL 方式. 个人认为  PDO 的好处有效率高  代码简洁 通用性好  这代码稍作改动就可以拿去脱mssql 不过用php和mssql组合的应该不多- -

SQLMAP脱裤

之前就有一个朋友问,咋使用sqlmap脱裤.然后我丢了一个参数给他,他好像懵逼懵逼的.今天又有一个哥们儿在群里问,行吧.就直接教一下. 其实很简单. --dump这个参数就是用来脱裤的哟.如果你要拖整个表的话你可以加个-all(--dump-all) CODE: sqlmap.py -u "http://127.0.0.1/index.php?id=1" --dump -D sqlinject -T admin -C "id,username,password" 脱

仿5173游戏交易平台系统SQL注入(可直接脱裤)+Getshell

最近没事登登好几年前玩过的游戏看看,发现有人喊高价收号,这一看就是骗子,这等骗子还想骗我?我就来看看这逗逼是怎么骗人的,结果发现这人给了一个说是 5173平台交易的网站,叫我直接把号的信息填上去然后填好了之后就去他就会去购买,然后仔细看了一下平台,获取了源代码后看了一下~呵呵,漏洞还是有不 少的~ 仿5173网游交易平台游戏交易平台存在注入与getshell漏洞,可直接拖掉玩家数据~     发乌云上乌云不收,所以没事就发zone里给大家玩玩.其实这系统还是蛮多漏洞的,我最痛恨骗子了,大家能搞几

大麦网疑遭“脱裤” 600余万用户信息被售卖

乌云漏洞平台报告,一些黑产交易论坛正售卖传播一份大麦网用户数据库,其中包括账号邮箱,密码hash等信息.经过测试,泄漏的账号均可成功登录,大麦网目前已确认该问题.另有用户反映通过大麦预订的演出票未取票订单信息已成空白,常用大麦的朋友要小心了! 白帽子黑客起初发现有大麦网用户数据库在黑产论坛被公开售卖,于是对泄露的用户数据进行验证,发现相邻账号的用户ID也是连续的,并均可登录.因此,丛技术的角度可以初步证明本次大麦网的数据泄露有很大拖库嫌疑(网站用户注册信息数据库被黑客窃取). 目前这一漏洞问题已

OSQL.EXE 命令行下脱裤mssql

cd C:\Program Files\Microsoft SQL Server\100\Tools\Binn\ OSQL.EXE -S "localhost" -U "sa" -P "123456789"  -q "select [name] from [sysdatabases] order by [name]"  查询所有库 ------fwwebmastermodelmsdboadataReportServerRepo

命令行下连接SQLServer小工具(脱裤必备)

osql -S 192.168.2.xx -Ufxxxx -PHxxxxx  -Q "use xxx;select  * from xx"  -o %temp%/xx.txt -w  20000

由脱库攻击谈口令字段的加密策略——密码泄露事件杂谈之一

转自:http://blog.sina.com.cn/s/blog_61efbd3c01012wmx.html (原作者:江海客 知名网络安全专家,安天实验室首席技术架构设计师.) 我不得不惨痛地写在前面的是,这是一个安全崩盘的时代.在过去一年,已经证实遭遇入侵的.并导致关键数据被窃或者被泄露的公司,包括索尼.世嘉这样的大型游戏设备厂商,包括花旗银行这样的金融机构,也包括了RSA这样的安全厂商. 这些事件中最令业界瞠目的是RSA的被入侵,这导致多家工业巨头遭遇连锁地攻击,还有很多安全企业本身也使

1password密码库格式更新

由于国内网络安全做的太差,经常发生被脱裤的事件,比如最近的网易邮箱(via 乌云),所以只好用1password这类密码管理软件,实现一站一密.昨晚半夜冻醒了,刷推刷到了这个:1password-leaks-your-data,整个人吓醒了=_=# 作者有点标题党,脱水版可以参见reddit的这篇文章,大意是1password的旧密码库格式叫agilechains,大体是json结构,里面只有密码是加密的,密码项的名字和URL并未加密.官方提到历史原因,早期计算能力弱,只好加密关键部位.官方推出

从12306帐号泄漏谈用户密码安全

新闻回顾 12月25日圣诞节,据漏洞反馈平台乌云网显示,大量12306用户数据在互联网疯传.本次泄露的用户数据包括用户帐号.明文密码.身份证.邮箱等. 随后,12306官方发表公告,称经过认真核查,此泄露信息全部含有用户的明文密码.12306网站数据库所有用户密码均为非明文转换码,网上泄露的用户信息系经其他网站或渠道流出. 12月26日,中国铁路官方微博发消息,铁路公安机关将涉嫌窃取并泄露12306网站电子信息的两名犯罪嫌疑人抓获,并指出此次用户信息泄漏事件是犯罪嫌疑人"撞库"来完成信