安全登录的跨平台解决方案V1.1

Team: http://www.ph4nt0m.org
Author: 云舒(http://www.icylife.net/)
Date: 2007-11-23

最近在考虑一个安全可靠的,容易部署的方案来解决登陆的安全问题,因为这个问题随着网上银行,网络游戏等的兴起而越来越重要。之所以想跨平台,是因为最近很多的linux用户在网上讨论linux,firefox这些使用网银等时候遇到的麻烦。我恰好看了他们的很多讨论,除了口水之外没有别的东西,只废话而不做事的废柴太多了。因此,我就有了这么一篇文章,介绍一下怎么实现安全的登陆。题外话一句,我对web安全的各种技巧,其实没有太大的兴趣,虽然闲得没事也会偶尔玩玩,只是和我玩CS差不多而已。

一. 登陆面临的安全攻击

1. 键盘记录

键盘记录应该是目前最流行的盗取密码的方法了,攻击者在系统中使用全局键盘钩子,记录用户的按键操作,并根据用户窗口的标题来确定是不是自己需要盗取的东西。

2. 系统消息

用户在浏览器中敲完了密码之后,攻击者的程序给浏览器发送消息,要求取得密码输入框的值,随后保存并记录下来。在windows2000以后的系统中,做了一点改进,但是创建了远程线程之后就依旧可以了。

3. 传输捕获

攻击者在网络中劫持或者嗅探传输数据,直接获取明文密码。虽然现在https使用较多,但是https速度较慢,影响服务器速度,而且也存在比较严重的一些安全缺陷,并不是一种非常可靠的办法。关于https的劫持,可以看我的一个相关文章《如何进行https中间人攻击》,地址在http://www.icylife.net/yunshu/show.php?id=468

二. 当前的解决办法以及缺陷

1. 当前国内解决方案

目前国内最常见的解决办法是ActiveX控件加https的方式。使用ActiveX控件来保护输入不被键盘记录和伪造的系统消息获取, https来保证传输的隐秘性和完整性。招行,民生银行的登陆大致都是这样的模式,因此国内某些firefox用户比较不满。我曾经在一个帖子中说过键盘记录的问题,被说成是银行的枪手,这里就不说了。

2. ActiveX的缺陷

https的缺陷就不说了,很容易就可以伪造证书劫持传输,虽然会提示证书警告,但是有多少用户会在意了?而且国内不少银行自己的证书本来就会有安全警告提示。ActiveX的缺陷也很明显,首先只支持windows系统和IE浏览器;其次本身容易出现安全问题,造成溢出等攻击;最后,对于更底层的挂接I/O驱动的攻击比较为难,当然ActiveX也可以调用自己的驱动,但是成本太高了。

三. 跨平台的解决方案

1. 解决方案

我这里的方案是一个思路,不局限于语言。如果不想跨平台你可以使用ActiveX实现,如果需要跨平台可以使用java applet实现,甚至还可以使用flash来实现。利用的方法主要是随机键位的软键盘以及RSA非对成加密。RSA也是一个很有意思的东西,可以看看《RSA非对称加密的一些非常规应用》,地址为http://www.icylife.net/yunshu/show.php?id=471

目前常见的登陆都是html等语言作的,然后调用ActiveX控件或者java applet来输入密码。其实,最好的解决方案是直接使用java applet作一个form,用来接受用户名和密码,做出相应的处理后再登陆。

首先,在服务器端生成一对2048位的RSA密钥,私钥保存好,公钥则发布到网上,让客户端可以通过类似http://www.test.com/login/publickey.txt的域名来进行访问。

其次,在客户端用java applet作一个form来等待用户输入。用户名常规方法输入,而密码框得到焦点时,弹出虚拟键盘。键盘每个键的位置随机出现,防止别人记录。而在 java applet中,有一个变量real_pass,在用户点了一个键,比如说是点了a的时候,real_pass += 'a',同时在密码输入框中随机输入一个字符,直到用户密码输入完成。这个时候,真实的密码记录在real_pass变量中,而密码输入框中是一个伪造的密码。

再次,用户点击提交按钮的时候,客户端从服务端获取RSA公钥,对real_pass进行RSA非对称加密,然后提交到服务端等待认证。

2. 优势

最明显的优势是使用了java applet来进行客户端操作,而java是可以跨平台,跨浏览器的。因此firefox用户,linux用户都可以成功的使用。其次,java是一种安全的语言,不会存在ActiveX自身容易出现的缓冲区溢出等安全问题。

3. 缺陷

使用java applet的缺陷主要有三点:第一,jre过于庞大,而且还没有普及到所有的用户当中;第二,jre也出现过一些溢出类的安全漏洞,因为jre本身是使用c写的;第三,java applet的运行速度不如ActiveX快。当然,可以使用ActiveX技术实现同样的思路,只是那样就不能跨平台了,违背了设计的初衷。

四. 总结

这个只是安全登陆的一个思路,和具体的语言以及平台都没有关系,可以用java applet实现,可以用ActiveX实现,甚至还可以使用js来实现,只要你能用js画出那个键位随机的键盘,后面的真假密码,以及RSA加密等js 实现起来就不难了。其实js也是个不错的选择,而且还没有客户端环境需求。关于钓鱼的内容,我们team的刺写过一些文章,我就不多说了。本文可以随意转载,但是请保留出处和版权,并且不得用于商业用途,谢谢。

五. 补充

下午写完这个方案后发布到了我们team的blog和邮件列表,算是1.0版本。后来和刺,螺螺做了一番讨论,还谈到了上面说过的《RSA非对称加密的一些非常规应用》中关于代替https的部分。这里确实存在一个安全缺陷,因此作了这个补充,算是这个方案的1.1版。

主要是因为用JS来实现RSA加密代替HTTPS,也存在中间人攻击的问题。明文传输的JS中保存了public key,攻击者可以作中间人,在客户端请求服务端的时候,替换掉这个public key,从而得到传输的密码。

在现在提出的这个解决方案的1.0版中,我提出"在服务器端生成一对2048位的RSA密钥,私钥保存好,公钥则发布到网上,让客户端可以通过类似http://www.test.com/login/publickey.txt的域名来进行访问。“这样其实是不够安全的。这么作的原因是可以很方便的修改public key而不用重新编译java applet或者flash程序,但是带来的后果是如果有人在传输这个public key的时候劫持了会话,可能会自己生成一对RSA密钥,将其中的公钥作为真实服务器的公钥传递给登陆用户,最终可获取传输的明文密码。

解决这个问题并不困难,有两个办法:第一,可以使用https的方式来传输这个public key,像https://www.test.com/login/publickey.txt这样来访问。在出现证书报警的时候提示用户不要进行下一步操作,终止整个登陆过程。这样public key依旧可以方便的修改而不用重新编译。如果要更高的安全性,可以整个过程都使用https来进行。第二,如果因为HTTPS会给服务器带来较大运算压力而又不想买硬件加密卡,也可以将public key直接写在java applet或者flash中。这样不用每次去抓取public key,只是定期更换public key会比较麻烦,需要重新编译java applet或者flash程序。

最后,说一下屏幕截取。刺提起过这个问题,其实我在构思这个解决方案的时候,就想到了这种攻击。不过屏幕截取来查看用户的鼠标点击,还是比较困难的,难以截取准确的时间段。防御的方法,或许就只能写驱动了。

关于刺的文章,可以在我们的blog查看,url为http://pstgroup.blogspot.com/2007/11/tipsqqrsa.html。腾讯的注册那里,使用的js加密代替https的方法,可以看我以前写的文章。他们会不会买硬件加密卡了?呵呵。

相关日志

发表评论