如何设计一个安全的账号系统?

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

1.用正确的姿势保存密码

低级错误:明文保存密码

安全性最低的是在服务端明文保存用户的密码,一旦服务器被入侵,数据被拖走(拖库),所有用户的密码都直接的暴露在外面。

低级错误:可逆加密密码

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

错误方法:md5 加密密码

这是早期比较主流的做法,然而,这依然是非常不安全的。因为只要枚举所有短密码进行 md5 加密,做成一个索引表,就能轻易的逆推出原始密码。

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

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

一个健壮的、牢不可破的系统应该是:即使被拿走了数据和所有的代码,也没办法破解里面的数据

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

  1. 使用更安全的 hash 函数用来抵抗碰撞攻击,比如:SHA256, SHA512, RipeMD, WHIRLPOOL。
  2. 可以使用一种大量消耗 cpu 的 hash 算法对抗暴力破解,比如PBKDF2 或者 bcrypt。
  3. 比较加盐 md5 结果时,使用时间恒定的比较函数。
  4. salt 的值不要和最终 hash 的结果存在同一个数据库。
  5. 最终存储的结果使用基于 key 的 hash 函数,比如 HMAC。 key 从外部安全性极高的专属服务中获得。

一些防范的方法

  • 要求密码强度,做弱密码检测
  • 安全系数较高的验证码
  • 防止机器人。使用有一定干扰的检验码,有失效时间。
  • 异常登录检测或提示上一次登录时间地点。密码错误锁定。
  • 错误回显不要太多。
  • token超时重新登录机制。
  • 找回密码的安全性不能低于密码认证。慎用邮箱找回,重置密码链有必要的话要做到确认用户信息后才可以设置密码、重置密码。
  • 可以考虑让用户预留与密码无关的个性提示信息,用于防钓鱼网站

2.用正确的姿势传输数据

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

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

验证服务端的合法性

加密技术:对称加密 和 非对称加密。 对称加密:加密和解密时使用的是同一个密钥。非对称加密:需要两个密钥来进行加密和解密:公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥) ,公钥加密的信息只有私钥才能解开,私钥加密的信息只有公钥才能解开。
非对称加密是实现验证服务端合法性的基础,常见的加密算法有 RSA 、 ECC 等 。服务端生成一对公钥和私钥,公钥是公开的所有人都知道,客户端需要和服务端通信时,使用该公钥进行数据加密,由于只有真实合法的服务端才拥有对应的私钥,所有只有真实的服务端才能解密该信息,然后返回数据给客户端时,使用客户端自己生成的公钥进行加密,这样数据只有对应的客户端才能理解。
使用 HTTPS 时,数字证书里包含了名称和公钥信息,只要认证该证书是合法的,并且对方能理解用该公钥加密的信息,就能确定是合法的服务端。

确保通信的安全

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

防御重放攻击

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

  • 使用时间戳。
  • 数据包在一定时间范围内才是有效的。
  • 使用递增的序号。收到重复的数据包时可以轻易的发现。
  • 使用提问应答方式。
  • 收到数据包时可以判断出来是否应答过。
    HTTPS 正是使用了上述的原理,保证了通信的安全。所以,任何对安全有需求的系统都应该使用 HTTPS。如果是使用自有协议开发,比如 APP 或游戏,应该使用上述的方法保障通信的安全。

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

那用户其他的敏感信息呢?比如身份证、银行卡、信用卡等信息,该如何加密保存而不被泄露呢?

敏感信息加密。把敏感信息加盐hash处理。传输需要把认证过程放在SSL里用对称密钥通信加密。cookies也不能用持久型cookies,总之敏感信息不落地,要加密传输。敏感信息做no-cache。会话加令牌避免重用。

  • 对于身份证信息,可以像密码一样只保存 hash 的结果,可以用于用户输入身份证号后进行验证。假如需要给用户显示身份证信息,只需要保存抹掉了几位数字的身份证号。
  • 假如你的系统涉及到支付,需要用户的银行卡,信用卡(卡号,CVV码)等信息时,必须遵循 PCI DSS (第三方支付行业数据安全标准)标准。PCI DSS 是由 PCI 安全标准委员会的创始成员(visa、mastercard、American Express、Discover Financial Services、JCB等)制定,力在使国际上采用一致的数据安全措施,包括安全管理、策略、过程、网络体系结构、软件设计的要求的列表等,全面保障交易安全。
  • 如果只是银行卡,还需要遵循 ADSS (银联卡收单机构账户信息安全管理标准) 标准。

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

人员和技术

  • 使用现有cms时,有能力就进行代码审计,否则要隐藏cms指纹,时刻关注安全动态,打补丁。
  • 业务逻辑漏洞需要进行经常性的测试,比如密码找回,支付问题,平行垂直权限等。某些业务操作,最好设置验证码验证,或者token等。尤其是新上线的项目。
  • 关注组件漏洞,如框架、中间件、OpenSSL等,及时更新
  • 不能在生产做调试、测试,以免泄漏调试信息
  • 在新试用某一项技术前,一定要评估好该技术可能带来的风险,比如服务器代为远程请求数据时是否会造成ssrf问题,通过xml请求数据时,是否会造成xxe,flash的权限问题,callback的问题,OAuth认证,sso认证等等。
  • 员工培训,弱口令问题,上传代码到github等第三方,svn,备份,员工的安全意识,不随便在办公网打开未知文件,客服后台访问时禁止JavaScript执行等等。

服务器

  • 安装waf防火墙
  • 参数化查询或白名单防注入。
  • 同时做好权限控制,并对访问记录做好监控,及时发现问题,保留现场证据。
  • 网站做好日志记录,不定时进行审计。
  • 网站最好挂个cdn,来缓解直接的攻击。
  • 服务器打补丁,装防护软件,如安全狗。
  • 服务器各端口运行服务时,一定要保证鉴权,如mongodb等等。
  • 服务器各服务最小权限原则。
  • 后台等敏感路径要隐藏起来,或者验证IP。

数据和备份

  • 防SQL Injection。
  • 使用pdo来进行数据库查询,数据库权限不要太高,站库分离。
  • 备份的安全性不能低于生产。
  • 数据备份是为了防止由于硬盘损坏或人为破坏导致的数据丢失。磁盘 raid,物理备份(磁带库),异地的逻辑备份。
------本文结束感谢阅读------