登录模块 设计

如何设计一个安全的登录模块

原始 设计

默认数据表结构

1
2
3
id
phone
password md5(密码)

登录请求及代码

HTTP请求

1
2
3
4
5
6
7
8
9
10
11
12
$phone = htmlentities($_POST['phone']);
$password = htmlentities($_POST['password']);
$password = md5($password);

// 从数据库中获取加密后的password
$sql = "select password from user where phone = " . $phone . " limit 1";
$info = querySql($sql);
if ($info['password'] === $password) {
//设置cookie & session
} else {
echo "登录失败";
}

安全性

密码

一旦数据表遭到泄露,则所有账户及密码遭到泄露,密码采用md5加密。虽然md5算法是不可逆的,但是网上有彩虹表,可以根据彩虹表来得到密码。
假设数据库存储的password有一个值为d591e603e5668d1b2b5f2f6d3bdc44b0
通过彩虹表可以得到密码是xpisme

HTTP传输 (明文传输)


窃听者盗取信息后,就可以拿着这些账号密码进行登录了,进行购买商品,转账等操作。

进阶(加盐值) 设计

默认数据表结构

1
2
3
id
phone
password md5(密码+固定盐值)

登录的请求及代码

假设盐值是固定的funcking attack

HTTP请求

1
2
3
4
5
6
7
8
9
10
$phone = htmlentities($_POST['phone']);
$password = htmlentities($_POST['password']);
// 从数据库中获取加密后的password
$sql = "select password from user where phone = " . $phone . " limit 1";
$info = querySql($sql);
if ($info['password'] === $password) {
//设置cookie & session
} else {
echo "登录失败";
}

安全性

密码

根据彩虹表破解刚才传入的值bd4123fb562b60e196b832133db408ca

加盐值之后,彩虹表破解的难度增加。即使数据表遭到泄露,攻击者仍然很难破解出明文的密码。

HTTP传输 (明文传输)


窃听者盗取信息后,就可以拿着这些账号密码进行登录了,进行购买商品,转账等操作。
但是经过HTTP协议传输,仍然还会出现被窃听的风险。

HTTP 采用RSA加密

采用RSA算法,非对称加密。
客户端采用公钥加密,服务端采用私钥解密。

  1. 服务端提供获取公钥的接口
  2. 拿到公钥后,对密码进行加密,然后在进行登录

窃听者通过充当中间人的身份,即可获取正常的密码。

  1. 窃听者生成自己的公钥、私钥
  2. 给客户端自己的公钥
  3. 客户端采用窃听者的公钥后加密,传给服务器
  4. 请求被监听者拦截,用自己的私钥解密
  5. 将解密后的密码,再用服务端的公钥加密

最终的设计 (HTTPS)

默认数据表结构

1
2
3
id
phone
password md5(密码+随机盐值)

登录的请求

  1. 盐值是随机的,每个账号对应一个盐值,服务端维护这样的关系。盐值可以是创建时间、可以是用户名、邮箱等等、也可以是随机数。
  2. HTTP请求服务端获取该账号对应的盐值
  3. HTTP根据上一步获取到的盐值,对密码进行加密后,再登录。

安全性

  1. 破解密码 比起固定盐值,破解的难度也是大大增加。
  2. HTTPS传输 窃听者只能拿到HTTPS加密后的信息,也不能模拟登录。

Q&A

Q1: 为什么要加盐值?加了盐值就安全了吗?加盐的原理是什么?
A1: 如果不加盐值,则密码很容遭到破解。列如d591e603e5668d1b2b5f2f6d3bdc44b0,通过彩虹表就可以查到密码是xpisme;加了盐值只是提高了破解的难度,并不是真正的安全,当破解的成本大于收益的时候,破解也就没有了意义;加盐的原理是 md5(password + 盐值)。
Q2:为什么要使用HTTPS协议?
A2:因为HTTPS,会对传输的内容进行加密。窃听者即使获取信息,信息也是听过HTTP(SSL)加密后的。
Q3:有同学会说利用charles、fiddler等抓包工具,也可以抓到https接口的数据,是不是https也是不安全的?
A3:web中你能抓到是因为还没有经过SSL加密,SSL是在应用层和传输层中间,请求是在应用层前拦截的,没有经过SSL,所以能抓到明文的。抓app的包是因为手机安装了证书。这篇文章是个反例https://blog.csdn.net/stpeace/article/details/78073288 一定要看评论,评论才是正解。

参考资料
https://stackoverflow.com/questions/962187/plain-text-password-over-https
https://gooroo.io/GoorooTHINK/Article/13023/The-difference-between-encryption-hashing-and-salting/2085#.WyHeyHv-jIU
https://mp.weixin.qq.com/s/9ZB923jDybc143UKl1BRmQ
彩虹表: https://crackstation.net/

xpisme wechat
微信号