技术

用户认证(Authentication)的安全问题

Tags: ,

-2019年7月2日

前言

用户认证是多数系统不可获取的一个功能模块,用于认证登录进系统的合法性。由于此功能模块的存在是为了解决系统的安全问题,故避免模块本身的安全问题尤为重要,否则为了解决安全问题而引入了其他不安全则得不偿失。本文旨在研究用户认证模块实现中所面临的安全问题和解决思路,以期能够总结出在业务系统开发中遇到某一类问题的抽象归纳、分析分解、解决问题的一般性思路和方法。

用户认证的定义

用户认证是指用户在与系统交互时通过人机交互的方式向计算机表明自己的身份,计算机在收到用户输入后进行认证该用户是否是一个合法的用户的过程。

用户认证的一般流程

1,用户(User)输入账号信息(Account)到计算机(PC),回车表示输入完毕;

2,计算机(PC)进行计算(C1);

3,将计算结果(R1)发往(transfer)远程计算机(Remote PC);

4,远程计算机接收到PC发来的数据(R1’);

5, 远程计算机从DB查询到数据(D1);

6, 远程计算机通过计算(C2)得出结论:用户是否合法;

7, 将结论返回给PC,PC给用户展示是否认证成功;

8, 认证过程结束。

我们分别来看每个过程中的安全问题有哪些,如何解决:

步骤1:因为用户在界面中输入账号信息,所以存在的不安全因素通常是用户的输入被监听或者录像。

监听用户输入需要在计算机上事先安装监听用户键盘输入的窃听软件。从系统开发角度来看,这种情况通过从系统自身的角度无法解决或减轻或避免。

用户输入被录像同样属于计算机已经被别人控制,通过安装录屏软件录制屏幕。另外,用户在输入的时候周围有人可以观看屏幕也可以归类为屏幕输入被录制的问题。这个问题通过让用户输入的密码信息在屏幕上显示为特殊字符的方式就可以解决。在Linux系统中,解决方法更具有安全性:将用户密码输入不回显,这样提高了安全性但也降低了用户体验,所以在业务系统中很少这么做,而是通过圆点·或者星号*来代替用户输入的每一个字符,这种思想本质上是一种编码,用来解决明文直接暴露的问题。它和早起军事上所用的电报效果类似,都是将明文进行编码防止直接暴露,不同在于电报需要反解密而此处的字符替换仅仅是视觉替换而已。

步骤2:除了系统代码存在漏洞之外,这一步可以认为没有安全问题,代码漏洞不在本文的讨论范围。

步骤3:由于数据从PC发出要流经网络很多节点最终到Server,这个过程可能会发生数据在传输途中被劫持的可能,劫持之后既可以偷窥也可以篡改。

不论劫持后怎么利用,都是不安全的。所以为了从根本上解决问题,就需要杜绝数据被劫持,但这一点是很难做到的,原因在于数据流经Internet中的节点绝大多数不在我们的控制范围内,比如可能是运营商的设备,也可能是社区专线代理商的设备等等,只要数据从这些设备上流过,就有可能被劫持,或者说就无法避免被劫持。

通常的解决办法不论是HTTPS还是对传输的密码MD5,都只是解决数据被劫持后无法窥探的问题,并不是解决数据无法被劫持的问题。

HTTPS暂且按下不表,后面如果有时间可以专门写一篇讲述HTTPS协议的文章。

我们来看看对密码进行MD5解决了什么问题?

试想一个问题,即使密码MD5之后传输,但别人劫持了之后依然可以拿到密码的MD5值,然后向Server的认证接口发送类似于劫持到数据,认证任然会被通过。换句话说,黑客根本不需要知道你的密码原始值,他从中间劫持到你的数据之后拿到的MD5值正好是他需要的,如果他拿到原值要认证还是需要再MD5一遍,相当于他拿到的是你帮他MD5过了。那这个MD5有什么用呢?

答案就是,为了防止黑客劫持到明文密码后用你的账号密码去尝试其他的网站或系统,因为很多人习惯于一个账号密码到处使用。

所以,对密码MD5对本系统是没有用处的一个安全手段,仅仅是为了保障用户其他系统的账号密码安全做的一个措施。当然,此手段也仅仅是降低了账号信息被劫持之后安全问题,并不能完全杜绝,比如现实中类似彩虹表之类的数据就可能将MD5密码值对比找出原始密码。

步骤2中提到的计算C1,往往包括将密码进行MD5的计算。

步骤4:这一步的目的是解析协议,反序列化对象,从数据中剥离出业务所需的用户认证时提交的信息,除非有代码漏洞,否则可以认为没有安全问题。

步骤5:这一步同步骤4。

步骤6:这一步的计算逻辑通常包括如下流程:

我们来看判断是否是合法用户的计算是什么样的,一种比较好的实践通常类似这样:

将用户提交的密码进行MD5计算,然后和从DB中查到的账号信息的密码对比,如果相等则为合法用户,否则为非法。

这里有个很重要的点:将用户提交的密码再MD5。这样做的原因在于:在用户注册的时候,用户提交的密码在PC端进行了MD5之后传输给Server,Server进行了二次MD5之后插入到了DB,所以此时登录认证时在Server端同样需要二次MD5才能和DB中的密码进行比较。

那为什么注册时需要在Server端进行二次MD5呢,这样做的作用是什么,难道是两次MD5更不容易逆向解密吗?答案当然是否定的,即使一次MD5,也足以保证无法逆向解密,当今世界如果谁有能力逆向MD5,那他就不需要做黑客了,直接去全世界名校去做密码学教授就行了。

对密码进行二次MD5再落库的目的是为了防止数据库被黑客脱掉之后的安全问题,当然此手段只是为了保证脱库后安全问题降到最低,并不能保证脱库后就没有问题。

解释一下为什么这么说,假如表中存储的是一次MD5后的值,当库被黑客脱掉之后就会和步骤3被从中间劫持的效果是一样的。而如果二次MD5,黑客拿到的账号并不能直接通过Server的认证接口去认证,因为黑客提交被二次MD5的值到Server之后,Server会进行三次MD5,这样就和表中密码不一致,从而认证失败。

步骤7:虽然步骤7也要经过网络传输,也可能会被劫持,但步骤7的数据为Server对PC的应答数据,劫持此数据基本没有用处,唯一的用户就是往数据中植入脚本在用户计算机上插播广告,当然广告中也可以插入恶意脚本,但这个问题是所有数据在网络传输都面临的问题,并不是用户认证特有的问题域,所以不做过多解释,如果要杜绝也仅有HTTPS一种方案,记住仅有HTTPS一种方案,任何试图自己通过代码逻辑尝试去不论加解密也好还是其他任何手段也好,都行不通,否则你就可以砸了所有现有CA证书厂商的饭碗,或者你搞来搞去最终发现你的方案最终还是HTTPS的方案。

Leave a Comment