`
FengShen_Xia
  • 浏览: 279269 次
  • 性别: Icon_minigender_1
  • 来自: 东方水城
社区版块
存档分类
最新评论

【转载】设计安全的账号系统的正确姿势

 
阅读更多

【文章来自:http://blog.coderzh.com/2016/01/03/security-design/】

 

security

 

 

引子

最近有个虚拟练习项目,涉及到系统安全保障的设计,于是对安全保障这块做了一些更深入的了解。发现了很多有趣的东西,开阔了眼界。中间查了一些资料,于是我打算重新整理,用更加循序渐进,大家都能懂的方式,说一说如何设计一个安全的系统。

 

著名的安全事件

首先来看看最近几年比较著名的拖库撞库后密码泄露的事件:

  1. 2011年12月,国内最大的程序员社区 CSDN 遭拖库,600万个账户信息泄露。
  2. 2014年3月,携程旅行网的系统存技术漏洞,漏洞可能导致用户的姓名、身份证号码、银行卡类别、银行卡卡号、银行卡CVV码以及银行卡6位Bin泄露。
  3. 2014年5月,小米论坛涉及800万用户信息遭泄露,信息包括用户名、密码、注册IP、邮箱等。
  4. 2014年12月,12306遭撞库攻击,13万用户信息泄露,包括用户账号、明文密码、身份证、邮箱等敏感信息。
  5. 2015年10月,网易邮箱遭攻击,近5亿条用户信息被泄露,包括用户名、密码、密码保护信息、登陆IP以及用户生日等多个原始信息。

除了密码泄露事件,数据被物理删除的事件也是发生:

2015年5月,携程网及APP陷入瘫痪,数据库遭物理删除疑似离职员工报复。

这么多大公司大网站的系统都遭到攻击,泄露用户信息,更别说其他小网站了。这些攻击都可以从技术上来进行防范的,但是我们看到即使是大公司,安全方面也是那么的薄弱。

 

防范方法

防范的方法简单来说数据从用户键盘敲出的那一刻,到服务器后台存储都要保持正确的姿势。比如:

  1. 用正确的姿势保存密码。
  2. 用正确的姿势传输数据。
  3. 用正确的姿势加密敏感信息。
  4. 用正确的姿势对数据进行备份和监控。

用正确的姿势保存密码

这一步非常重要,也比较复杂。用户在浏览器里输入密码,传输到服务器端进行验证,服务端将之前保存的密码信息和用户的输入进行比对。

 

1. 低级错误:明文保存密码

安全性最低的是在服务端明文保存用户的密码,一旦服务器被入侵,数据被拖走(拖库),所有用户的密码都直接的暴露在外面。这是最初级的做法,毫无安全性可言。假如你在一个网站或论坛注册了一个账号,该网站自动发了一封邮件告诉你注册成功,里面明文写了你的密码,赶紧把密码改了然后再也不要访问这个网站。

 

2. 低级错误:可逆加密密码

既然不能明文保存密码,那当然是加密保存了。耍个小聪明,比如把密码的字母倒着存,或者每个字母存后一个字母,或者进行异或混淆处理,表面上密码看上去已经看不出来原始的密码是什么了,但实际上这个和明文保存密码并没有本质区别,因为黑客既然可以入侵你的服务器,自然可以拿到你的加密代码,只要按你的算法进行简单的解密就可以得到原始密码。

 

3. 错误方法:md5 加密密码

在我还是一个初学者的时候,我已被告知不能用前两种方式保存密码,当时的主流方法是使用 md5 加密密码。(年代久远,现在已绝非主流了。) md5 是一种不可逆的加密方法,即密码被 md5 加密后是无法解密出原始密码的,验证密码是否正确的方法是将用户输入的密码 md5 加密后于数据库里保存的 md5 机密后的结果进行比对。这样,服务器端在不知道真实用户密码的情况下也能对用户密码进行验证了。

 

这是早期比较主流的做法,然而,这依然是非常不安全的。因为只要枚举所有短密码进行 md5 加密,做成一个索引表,就能轻易的逆推出原始密码。这种预先计算好的用于逆推加密散列函数的表就是“彩虹表”。随着“彩虹表”不断变大,md5 的加密已经变得非常的不安全。2015年10月网易邮箱的用户密码泄露也被怀疑只对密码进行了 md5 加密。

 

4. 正确方法:加盐 hash 保存密码

加盐 hash 是指在加密密码时,不只是对密码进行 hash ,而是对密码进行调油加醋,放点盐(salt)再加密,一方面,由于你放的这点盐,让密码本身更长强度更高,彩虹表逆推的难度更大,也因你放的这点盐,让黑客进行撞库时运算量更大,破解的难度更高。

 

如何进行加盐就是一门很重要的学问了。md5 是一种 hash 算法,以下就拿 md5 来举例。假如密码是 123456 ,md5 的结果如下:

md5

像 123456 这样的简单密码,是很容易被逆推出来的。但是假如我们往简单密码里加点盐试试:

md5-salt

上面例子里的 #g5Fv;0Dvk 就是我们加的盐。加完之后,密码的强度更高了,彩虹表破解的难度加大了。或者进行加盐两次 md5 :

double-md5-salt

到这里,你一定会有疑问,是不是把 md5 多做几次,或者自定义一些组合的方式就更安全了。其实不是的,黑客既然能拿到数据库里的数据,也很有可能拿到你的代码。

 

一个健壮的、牢不可破的系统应该是:

即使被拿走了数据和所有的代码,也没办法破解里面的数据。

这也是为什么大家不必实现自己的加密算法,而是使用公开的加密算法的原因,比如:RSA、AES、DES 等等。既然无法保证加密代码不被泄露,那就使用公开的加密算法,只要保护好私钥信息,就算你知道我的加密方式也没有任何帮助。

 

大部分情况下,使用 md5(md5(password) + salt) 方式加密基本上已经可以了:

salt

其中,最关键的是 salt 从哪里来? salt 该怎么设置才能安全。有几个重要的点:

  1. 不要使用固定不变的 salt。
  2. 每个用户的 salt 都需要不同。
  3. salt 要保持一定的长度。
  4. salt 必须由服务端使用安全的随机函数生成。
  5. 客户端运算需要的 salt 需要从服务端动态获取。
  6. 客户端加盐 hash 的结果并不是最终服务端存盘的结果。

由于客户端也需要执行加盐 hash ,所以,salt 不能直接写在客户端,而是应该动态从服务端获得。服务端生成随机的 salt 时,必须使用安全的随机函数,防止随机数被预测。

各语言安全的随机函数:

Platform CSPRNG
PHP mcrypt_create_iv, openssl_random_pseudo_bytes
Java java.security.SecureRandom
Dot NET (C#, VB) System.Security.Cryptography.RNGCryptoServiceProvider
Ruby SecureRandom
Python os.urandom
Perl Math::Random::Secure
C/C++ (Windows API) CryptGenRandom
Any language on GNU/Linux or Unix Read from /dev/random or /dev/urandom

就算 salt 值动态从服务端获取,也有可能被中间人拦截获取。同时,客户端的加盐 hash 的过程相当于是完全暴露的。一种更安全的做法是,客户端使用 javascript 进行加盐 hash,把结果传到服务器后,服务器对结果再进行一次 加盐 hash 或者 加密 hash(比如:HMAC) ,然后再和数据库的结果进行比对。

 

如果需要达到更高的安全等级,可以考虑:

1. 使用更安全的 hash 函数用来抵抗碰撞攻击,比如:SHA256, SHA512, RipeMD, WHIRLPOOL。

 

两个不同的内容 hash 的结果可能相同,攻击者在不知道真实密码的情况下,使用其他密码进行碰撞攻击从而登录系统。使用更安全的 hash 函数可以减少这种情况的发生。

 

2. 可以使用一种大量消耗 cpu 的 hash 算法对抗暴力破解,比如PBKDF2 或者 bcrypt。

暴力破解就是枚举所有可能的密码进行尝试验证,使用大量消耗 cpu 的 hash 算法可以极大增加暴力破解的时间。

 

3. 比较加盐 md5 结果时,使用时间恒定的比较函数。

在比较两个字符串时,通常都一个字符一个字符进行比较,如果某个字符不匹配就会立即返回。攻击者可以根据验证的时间长短来判断前几位字符是否正确,然后逐步修正最终得到正确的结果。

 

因此,在比较 hash 时,使用时间恒定的比较函数,可以让攻击者摸不着头脑。比如下面这段代码:

private static boolean slowEquals(byte[] a, byte[] b)
{
    int diff = a.length ^ b.length;
    for(int i = 0; i < a.length && i < b.length; i++)
        diff |= a[i] ^ b[i];
    return diff == 0;
}

异或(^)操作可以用来判断两个字符是否相等,比如:

0 XOR 0 = 0    1 XOR 1 = 0
0 XOR 1 = 1    1 XOR 0 = 1

上面的函数枚举每个字符进行异或判断,然后将所有的结果取或运算,得到最终的结果,比较的时间是恒定的。

 

4. salt 的值不要和最终 hash 的结果存在同一个数据库。

SQL 注入是常见的攻击手段,被注入后数据库里的数据被暴露无遗。所以,应该将 salt 分开存储,存到别的机器的数据库里,让攻击者拿不到 salt ,从而无法轻易破解信息。

 

5. 最终存储的结果使用基于 key 的 hash 函数,比如 HMAC。 key 从外部安全性极高的专属服务中获得。

 

有了这层加固,即使数据被拖库,攻击者也无法从 hash 的结果逆推回原始密码。因为使用了加密的 hash 函数。基于 key 的 hash 函数只是进行哈希运算时,除了传入原始内容外,还需要传入一个密钥(key)。攻击者没有 key 几乎不可能对数据进行解密。

 

key 可以保存在极高安全性的通用的 key 管理系统,使用加密协议传输,对访问者进行验证,只允许特定的机器有权限访问。

 

用正确的姿势传输数据

使用 HTTP 协议传输数据时,数据都是明文传输的,数据从发出到服务器接收,中间可能被劫持,篡改。比如常见的 DNS 劫持,HTTP 劫持,中间人攻击。

 

用正确的姿势传输数据,目的就是为了保证传输的数据安全,简单归纳为两点:

  1. 需要确保进行通讯的服务端是官方的、正确的服务端,而不是跟一个假的服务端在通信。
  2. 确保信息在网络上传输时是加密的,只有客户端和服务端有能力对数据进行解密。
  3. 确保信息在传输时不被篡改,或者数据被篡改时能立即发现。

1. 验证服务端的合法性

《改变未来的九大算法》一书中提到了公钥加密和数字签名技术,这是进行安全通信的基础技术保障。这里涉及到了加密技术,先了解两个最基础的概念:

  1. 对称加密:加密和解密时使用的是同一个密钥。
  2. 非对称加密:需要两个密钥来进行加密和解密:公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥) ,公钥加密的信息只有私钥才能解开,私钥加密的信息只有公钥才能解开。

非对称加密是实现验证服务端合法性的基础,常见的加密算法有 RSA 、 ECC 等 。服务端生成一对公钥和私钥,公钥是公开的所有人都知道,客户端需要和服务端通信时,使用该公钥进行数据加密,由于只有真实合法的服务端才拥有对应的私钥,所有只有真实的服务端才能解密该信息,然后返回数据给客户端时,使用客户端自己生成的公钥进行加密,这样数据只有对应的客户端才能理解。

rsa

使用 HTTPS 时,数字证书里包含了名称和公钥信息,只要认证该证书是合法的,并且对方能理解用该公钥加密的信息,就能确定是合法的服务端。

2. 确保通信的安全

既然使用非对称加密的方式,可以保证双方安全的通信,那是不是就一直使用非对称加密传输数据就行了?理论上是可以的,但是非对称加密的效率要比对称加密的效率低很多。通常的做法是,通过非对称加密的方法,协商出一个只有双方知道的对称加密密钥。

 

即使在不安全的通信环境下,也可以协商出一个只有双方才知道的对称加密密钥。在《改变未来的九大算法》一书里,有一个经典的描述如何交互密钥的例子(在所有沟通都是透明的情况下,如何协商出一个只有你和阿诺德才知道的颜料颜色。):

sharedkey

ECDH 就是基于上面原理设计的密钥交换算法:

ecdh

密钥协商好后,双方就可以使用该密钥进行加密传输了,比如使用 AES 、 DES。

由于 ECDH 密钥交换协议不验证公钥发送者的身份,因此无法阻止中间人攻击。如果监听者 Mallory 截获了 Alice 的公钥,就可以替换为他自己的公钥,并将其发送给 Bob。Mallory 还可以截获 Bob 的公钥,替换为他自己的公钥,并将其发送给 Alice。这样,Mallory 就可以轻松地对 Alice 与 Bob 之间发送的任何消息进行解密。他可以更改消息,用他自己的密钥对消息重新加密,然后将消息发送给接收者。

 

解决方法是,Alice 和 Bob 可以在交换公钥之前使用数字签名对公钥进行签名。

即使攻击者不能解密传输的内容,但仍可以使用重放攻击尝试身份验证或用于欺骗系统。重放攻击是指攻击者将数据包截取后,向目标主机重新发送一遍数据包。

 

防御重放攻击的方法主要有:

  1. 使用时间戳。数据包在一定时间范围内才是有效的。
  2. 使用递增的序号。收到重复的数据包时可以轻易的发现。
  3. 使用提问应答方式。收到数据包时可以判断出来是否应答过。

HTTPS 正是使用了上述的原理,保证了通信的安全。所以,任何对安全有需求的系统都应该使用 HTTPS。如果是使用自有协议开发,比如 APP 或游戏,应该使用上述的方法保障通信的安全。

用正确的姿势加密敏感信息

我们都知道,用户的密码不能明文保存,而且要使用不可逆的加密算法,只保存最终的 hash 结果用来验证是否正确。那用户其他的敏感信息呢?比如身份证、银行卡、信用卡等信息,该如何加密保存而不被泄露呢?

 

对于身份证信息,可以像密码一样只保存 hash 的结果,可以用于用户输入身份证号后进行验证。假如需要给用户显示身份证信息,只需要保存抹掉了几位数字的身份证号。

 

假如你的系统涉及到支付,需要用户的银行卡,信用卡(卡号,CVV码)等信息时,必须遵循 PCI DSS (第三方支付行业数据安全标准)标准。PCI DSS 是由 PCI 安全标准委员会的创始成员(visa、mastercard、American Express、Discover Financial Services、JCB等)制定,力在使国际上采用一致的数据安全措施,包括安全管理、策略、过程、网络体系结构、软件设计的要求的列表等,全面保障交易安全。

 

如果只是银行卡,还需要遵循 ADSS (银联卡收单机构账户信息安全管理标准) 标准。

2014年3月携程泄露用户银行卡信息就是因为没有遵循 PCI DSS 标准。

用正确的姿势对数据进行备份和监控

2015年5月的携程数据被删事件,就是数据备份没有做好的例子。数据备份是为了防止由于硬盘损坏或人为破坏导致的数据丢失。主要措施有:磁盘 raid,物理备份(磁带库),异地的逻辑备份。同时做好权限控制,并对访问记录做好监控,及时发现问题,保留现场证据。

总结

本文总结了设计一个安全系统的基本原理和方法,并没有举出一个特定具体的方案,因为不同的系统对安全性的要求各有不同,设计者应该根据自身系统的特点进行具体设计。比如加盐 hash 的具体实施方法,salt 值如何构成等等。

 

附录

常用的加密算法:

  1. 对称加密:DES3DES、TDEA、Blowfish、RC2、RC4、RC5IDEA、SKIPJACK、AES
  2. 非对称加密:RSAECC(椭圆曲线加密算法)、Diffie-HellmanEl Gamal、DSA(数字签名用)
  3. Hash 算法:MD2、MD4、MD5、HAVAL、SHA-1、SHA256、SHA512、RipeMD、WHIRLPOOL、SHA3、HMAC

DES、3DES、AES 区别:

  1. DES:1976年由美国联邦政府的国家标准局颁布,密钥为 56 位。
  2. 3DES:DES加密算法的一种模式,它使用3条56位的密钥对数据进行三次加密。
  3. AES:高级加密标准,是下一代的加密算法标准,速度快,安全级别高,用来替代原先的DES。密钥长度可以是128,192或256比特。
分享到:
评论

相关推荐

    研发效能度量的正确姿势与落地实践.pdf

    "研发效能度量的正确姿势与落地实践.pdf" 研发效能度量是指对软件研发团队的工作效率和产出质量进行评估和分析,以提高团队的整体表现和竞争力。本文将讨论研发效能度量的正确姿势和落地实践,旨在帮助研发团队和...

    burp https证书与关闭HSTS正确姿势

    burp https证书与关闭HSTS正确姿势,决定干货,希望大家喜欢。

    论手游新手引导的正确姿势

    论手游新手引导的正确姿势,可以下载参考,欢迎大家下载

    行业文档-设计装置-一种帽式不正确读写姿势纠正装置.zip

    "一种帽式不正确读写姿势纠正装置"的设计旨在解决这个问题,通过创新的技术手段帮助用户养成良好的读写习惯,预防因不良姿势引起的健康问题。 该装置的设计理念是将科技与日常生活用品相结合,以一种无侵入、舒适的...

    基于局域网技术的篮球训练姿势智能监控系统设计.pdf

    【基于局域网技术的篮球训练姿势智能监控系统设计】是一项旨在提高篮球训练效果的创新技术应用。系统设计的关键在于利用无线传感器网络和人工智能算法,对篮球运动员的训练姿势进行实时监控与分析。 首先,系统通过...

    课程设计 基于Matlab的异常姿势识别系统源码+GUI界面+说明文档资料+项目资料齐全.zip

    课程设计 基于Matlab的异常姿势识别系统源码+GUI界面+说明文档资料+项目资料齐全.zip课程设计 基于Matlab的异常姿势识别系统源码+GUI界面+说明文档资料+项目资料齐全.zip课程设计 基于Matlab的异常姿势识别系统源码+...

    大学生方程式赛车设计(整体车架设计、标准安全系统及座椅附件设计).zip机械设计毕业设计

    《大学生方程式赛车设计——整体车架设计与安全系统解析》 在当今的工程技术领域,大学生方程式赛车设计是一项极具挑战性的项目,它不仅要求参赛队伍具备扎实的理论知识,还需要创新思维和实践能力。本设计主要围绕...

    小学生正确握笔姿势.doc

    小学生正确握笔姿势 小学生正确握笔姿势是学习写字的基础,良好的握笔姿势不仅能提高写字速度和质量,还能预防手腕和肩部的疲劳和伤害。下面是小学生正确握笔姿势的要点: 一、基本要求: * 手腕平放,手掌微微向...

    行业文档-设计装置-一种姿势矫正碳素笔.zip

    这种碳素笔可能是一种创新性的产品,旨在帮助用户改善书写或使用笔时的姿势,从而预防因长时间不正确姿势导致的健康问题,如颈部、肩部和背部的疼痛。 在【标签】"行业文档-设计装置-一种姿势矫正"中,进一步明确了...

    奋斗的正确姿势1

    《奋斗的正确姿势1》这本书为我们揭示了在职业发展道路上如何正确规划和行动。书中的核心概念是建立一个“职业储备账户”,这是个人在职场中积累的资源,包括人脉、技能和品格,这些都能在面临职业变动时发挥关键...

    行业文档-设计装置-书写姿势矫正笔.zip

    "书写姿势矫正笔"是针对这一需求而设计的一款创新装置,旨在帮助用户,尤其是孩子们,培养正确的握笔姿势,预防因不正确书写姿势导致的手部疲劳和近视等问题。 【描述】: "行业文档-设计装置-书写姿势矫正笔.zip" ...

    450、基于单片机的智能看书姿势校准系统设计(原理图、源代码)

    450、基于单片机的智能看书姿势校准系统设计(原理图、源代码) 该系统为单片机的智能看书姿势校准系统,实现看书姿势语音提示、光照强度语音提示等功能; 功能: 1、使用51单片机为核心控制; 2、语音模块实现看书...

    小学生正确握笔姿势PPT学习教案.pptx

    "小学生正确握笔姿势PPT学习教案.pptx" 这篇PPT学习教案主要讲解小学生正确握笔姿势的要点和步骤。整个教案分为六页,分别讲解正确握笔姿势的要点、步骤、错误握笔姿势的图解和总结。 首先,正确握笔姿势的要点...

    行业文档-设计装置-儿童握笔姿势矫正器.zip

    《儿童握笔姿势矫正器设计解析》 在当今数字化时代,虽然电子设备逐渐普及,但传统的书写技能仍然是儿童教育的重要组成部分。握笔姿势的正确与否,不仅直接影响到孩子的书写质量,还关系到他们的视力健康和手部肌肉...

    行业文档-设计装置-握笔姿势矫正装置.zip

    《握笔姿势矫正装置》是针对握笔习惯与书写健康问题的专业设计文档,旨在通过科学的方式帮助用户改善不正确的握笔姿势,预防和纠正因握笔不当引发的手部疲劳、手腕损伤以及书写质量下降等问题。这份行业文档深入探讨...

    正确的读写姿势教(学)案.doc

    《正确的读写姿势》教案和...通过这个教案,教师可以系统地教授学生正确的读写姿势,并通过反复的实践和反馈,帮助他们建立并巩固这一重要的学习习惯。这对于预防近视、维护脊柱健康以及提高学习效率都具有深远的意义。

    人机系统的安全设计.pptx

    《人机系统的安全设计》是关于如何在设计和构建人机交互系统时,确保安全性的专业指导。这一领域关注的是如何通过科学的方法来优化人与机器的协作,以减少潜在的危险和事故。 人机系统的安全设计主要包括六个关键...

    行业文档-设计装置-握笔姿势校正笔.zip

    在实际使用过程中,握笔姿势校正笔通常会配备一些指示系统,如角度指示器或特定的握笔位置标记,帮助用户直观了解自己的握笔角度是否正确。此外,一些高级设计还可能集成智能技术,如传感器和APP配合,实时反馈握笔...

Global site tag (gtag.js) - Google Analytics