不安全信道上的RIA应用的用户注册以及认证机制(2) – 用户注册

在上篇中谈了如何认证用户请求,下篇也即本文的内容是关于如何让用户安全注册帐户。

在正题之前还想补充谈一下上篇的机制能否抵挡针对服务器端数据库的攻击。
密钥是明文存放在服务器端数据库的,和用户手中持有的密钥一致。一个心怀鬼胎的数据库管理员,他瞄一眼,就能拿到了用户的密钥。骇客直接攻破数据库后果也一样。

很自然,我们想到了用哈希(hash)函数,数据库不直接保存密钥明文而只保存经计算后的摘要。非常遗憾,这种措施对安全性没有任何提高,即使hash运算再多几轮,结果还是一样。

回想起HMAC的算法,为了对消息进行署名,必须有key的参与,这个key是否已经过hash是无关紧要的。
倘若服务器端保存的key是hash过的,由于hash的不可逆,服务器端的HMAC运算必须用这个key而用不了明文密钥。客户端的逻辑也必须对应,运算前需要对用户持有的密钥进行同样的hash运算得到key后才能进行HMAC运算。

一个开源系统,或者是源码可见系统(比如JavaScript RIA应用),加密逻辑是显而易见的。心怀鬼胎的数据库管理员或者骇客拿到hash后密钥的后果,和拿到明文密钥的相比,没有任何区别。他已经能成功在客户端制造署名。

虽然对本系统的安全性没有任何提高,但从社会工程学角度出发,只保存hash后密钥仍然是值得推荐的。很多用户在不同网站使用相同用户名和密码,一个网站hash密码泄漏的危害不至于蔓延到其他网站,明文密码泄漏的危害大家用脚趾头想想都知道。

从安慰领导和客户的角度出发,改成hash也能提高他们的心理安全感。

回到本篇正题。在不使用HTTPS的情况下,如何保证注册密码不泄漏?很显然,传输的密码必须经过客户端加密。客户端能加密,服务器端能解密,这不就是公钥系统干的事嘛。本篇使用安全成熟的RSA体制。

用户注册机制:
1.服务器端持有一对RSA PublicKey和PrivateKey。如何持有,就请自行解决了。参考上一篇博客,可以在Linux下用ssh-keygen制造。服务器端用Java写的话,还可以用Java产生。其他语言余虽然不太了解,自行生产应该也不困难。
2.客户端请求服务器持有的PublicKey。(GET请求)
3.客户端用PublicKey加密用户名和密码组成的明文内容,得到密文
4.客户端将密文作为URL的参数值,发起注册请求。(POST请求)
5.服务器端用PrivateKey解密收到的密文,取出用户名和密码,如果用户名可用,在数据库写入用户信息,返回“成功”的JSON数据;如果用户名不可用,返回用户名不可用的500错误
6.客户端处理响应。

OVER。就是这么简单。

来看一下弱点。
抓包窃听是有效抵挡了,但能否抵挡中间人攻击?非常遗憾,答案还是不能。
看一下中间人的攻击流程:

1. 客户端 —— 中间人 —— 服务器端
2. 客户端 —— 中间人 ——(请求服务器端的PublicKey)——> 服务器端
3. 客户端 —— 中间人 <——(返回服务器端的PublicKey)—— 服务器端 4. 客户端 ——(请求服务器端的PublicKey)——> 中间人 —— 服务器端
5. 客户端 <——(返回中间人的PublicKey)—— 中间人 —— 服务器端 6. 客户端 ——(注册请求)——> 中间人 —— 服务器端
7. 客户端 —— 中间人(用自己的私钥解密后,再用服务器端的公钥加密) ——(注册请求)——> 服务器端
8. 客户端 —— 中间人 <——(注册成功)—— 服务器端 9. 客户端 <——(注册成功)—— 中间人 —— 服务器端

中间人成功获取了客户的注册信息

无论是上篇的认证还是下篇的注册,都无法抵挡中间人攻击。能发动中间人攻击的,在欧美除了网络提供商,在天朝要加多一个ZF。骇客的力量也恁厉害了一点。
但余想强调的是,对一般应用的安全要求,本下篇以及上篇提出的体制已经足够。更高的安全要求,你就不舍得买一个SSL证书么?

本文目前尚无任何评论.

发表评论

XHTML: 您可以使用这些标签: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
:wink: :-| :-x :twisted: :) 8-O :( :roll: :-P :oops: :-o :mrgreen: :lol: :idea: :-D :evil: :cry: 8) :arrow: :-? :?: :!: