序言
作为一个软件开发者,提高软件的安全性是每个人都需要关注的。安全性涉及的面很广,比如Apk包是否做了代码混淆(提高反编译难度),数据传输过程是否安全,数据库存储的数据是否安全等。
今天,我们来探讨一下App登录模块密码传输的安全性。
可行方案
先给出一个比较可行的方案,后面会分析安全性是怎么体现的。
- 用户注册过程,客户端通过
rule1(pass)
得到一个编码后的密码串passStr
,然后调用注册接口把name/passStr
传给服务器保存(不能用明文密码传输保存) - 用户在登录页面填写了用户
name
和密码pass
后,点击登录按钮,客户端通过rule1(pass)
把明文密码转换为passStr
- 客户端发送请从服务器查询一个时间戳
ts
和随机盐salt
- 客户端按照一定规则
rule2(pass, salt)
生成一个加密字符串encryptStr1
,调用登录接口,把name/encryptStr1/ts
传给服务端 - 服务器接收到请求,根据
name
获取passStr/salt
,然后按照同样的规则rule2(pass, salt)
得到密码串encrptStr2
- 然后用
encryptStr2
与客户端传来的encryptStr1
进行比对,如果两者相同,则登录成功,返回一个会话给客户端。
上面的步骤中有些地方需要做一些说明:
- 服务端不能存储明文密码,但可以存储一个编码后的密文
passStr
,这个密文在用户注册的过程中客户端生成(根据用户输入的密码pass
按一定的规则rule1
生成),通过注册接口传给服务端,服务端保存在用户表中。 -
salt
应该具有时效性,可以设置一个比较短的有效期(如1分钟),一旦超过这个时间,salt
失效,通过salt
生成的加密串也验证不通过。
这么说可能不够形象,下面我用一张图来表示:
模拟盗取用户信息登录
针对上面提出的登录加密方案,我们考虑一下如何能够盗取用户的登录信息。
- 首先,我要说的是Https请求可以通过抓包工具获取通信内容,所以仅仅通过Https来保证安全是不可靠的
- 在手机中植入病毒,获取用户的输入行为,这种方式毫无疑问可以直接拿到用户的用户名跟密码,直接冒充用户身份登录
- 拦截用户的注册请求获取
passStr
,不过用户注册的行为是一次性的,所以不那么好拦截,我们就认为无法获取passStr - 拦截获取随机盐接口,那么攻击者就可以修改参数获取用户的随机盐
- 拦截登录接口,攻击者可以获取当次请求的
encryptStr1/name/ts
,用这些参数可以在salt有效期内冒充用户进行登录 - 攻击者反编译Apk,获取
rule1
和rule2
,但攻击者还是无法推算出passStr,所以还是无法冒充用户身份进行登录
综上所述,攻击者可以做的事情如下:
- 往用户手机中植入恶意病毒,监听用户输入操作,获取用户名密码,可冒充用户登录
- 拦截用户注册请求,获取
passStr
,拦截获取随机盐请求,知道获取salt
规则,反编译Apk,获取rule2
。知道这些信息的情况下,也可以冒充用户进行登录。但这种方式难度极大,主要存在以下几个难点:注册操作是一次性的,不太可能被拦截;要抓取Https请求包,需要在用户手机上安装证书,或者让用户在自己安装证书的手机上登录账号;APK会加入混淆规则,所以反编译难度比较高。总结来说,这种方式不太可行。 - 拦截用户登录接口,获取此次登录参数,在salt有效时间内,可以冒充用户登录,如果用户体系存在互踢机制,那么用户会发觉账号被踢,及时修改密码
总结
从以上分析可以看出,这种登录方案还是比较安全可靠的,用户密码和登录信息不易泄漏。当然,除了这种方式,还有很多其他方式也可以保证安全,比如非对称加密RSA算法,对称加密算法(用RSA加密秘钥)等。