4.3 对验证机制漏洞进行防范
电子通信已经成为所有行业的基本部分,包括医疗保健、电信、制药、零售、金融等,几乎所有这些行业都在全世界部署了它们自己的特制软件系统和解决方案,从而把它们的客户和业务伙伴连接在一起。
银行、保险、资产管理和股票市场等领域的金融机构必须满足非常严格的安全需求,必须保护它们的应用程序处理的所有电子数据。它们必须设计和实现能够满足这些严格的安全需求的软件解决方案和应用程序。换句话说,系统需要确保很高的安全合法性。
正如在FFIEC(Federal Financial Institutions Examination Council)致金融机构的信函(FIL-103-2005,2005年10月12日)“Authentication in an Internet Banking Environment” 中指出的:“在网上银行环境中,未经授权的或未正确识别的用户可能会进行欺诈、泄露客户信息、损坏数据或造成不可能实施的合约,从而给金融机构造成经济损失和名誉损失。” 这封信函强调了网络验证机制的重要性:“风险评估应该根据与网上客户可用的各种产品和服务相关的风险决定有效的验证战略。”因此,必须建立健壮的验证管理过程来实现验证和授权,这是成功实现安全的软件解决方案的关键因素。
4.3.1 设置安全可靠的证书
要解决身份验证问题,需要有配套的公钥基本设施来核实用户的真实身份。这些设施用来创建、管理、发布、收回数字证书。而数字证书正是你需要为站点使用HTTPS协议付费的事项。但是,什么是数字证书?数字证书又是如何保证信息更加安全的呢?
从更高的层次来讲,数字证书是将机器上的公钥和身份信息绑在一起的数字签名。数字签名担保某份公钥属于某个特定的组织和机构。
证书将域名(身份信息)和特定公钥关联起来,这就避免了窃听者将自己的服务器伪装成用户将要连接的服务器并进行攻击的行为。
要受到一般浏览器的信任,证书本身还应当受到CA的信任。CA公司对认证会进行人工核查,确定申请主体满足以下两个条件。
一是在公共记录中存在着这个人/这家公司。
二是需要签名的证书上标明的域名的确由申请主体实际控制。
当CA查证得出申请人属实,并且的确拥有这个域名的结果时,便会为证书颁发签证,盖上“已核准”的戳记,表明网站的公钥属于这个网站,而且可以信任。
你的浏览器中会内置一系列受信任的CA列表。如果服务器返回的是未经过受信任CA签证的证书,浏览器会弹出大大的警告,如图4-20所示,这就在系统中多了一层安全措施,不然,任何人都可以四处签售伪造的证书。
图4-20 浏览器发出证书警告
这样一来,即使攻击者将自己的公钥拿出来生成这份密钥,声称自己的伪造服务器就是“xxxx.com”,浏览器也会因为检查到“未经受信任CA签名的证书”而弹出提示。
以下是一些关于证书的其他事项。
(1)增强式认证。
在常规的X.509证书之外,增强式认证证书提供了更强力的认证。
要授予增强式认证证书,CA会对域名持有者做更加深入的查验(通常需要提供护照和水电费账单等信息)。
这种类型的证书,浏览器中大锁图标的显示位置背景也会变成绿色。
(2)在同一台服务器上运行的多个网站。
在HTTP协议连接开始之前进行的TLS协议握手流程,很有可能存在着多个网站存放在同一个服务器,使用相同IP地址的情况。
虚拟主机的Web路由是由Web服务器分发,但是TCP握手的过程,是发生在连接之前。整个系统的单张证书会被发送到服务器的所有请求之中,这种流程会在共享主机的环境中发生问题。
如果你正在使用Web主机上提供的服务,他们会在你使用HTTPS协议之前要求使用独立的IP地址,不然主体提供商就需要每次在服务器上有新站点时,取得新证书(并且向CA重新申请认证)。
4.3.2 对密码重置和忘记密码功能进行控制
执行安全的验证机制,不仅仅要同时满足几个关键安全目标,许多时候也需要牺牲其他目标,如易用性、成本、功能。
1.防止滥用密码修改的基本要求
(1)加一个简单图片验证码,基本确保是人在操作,而不是机器。
(2)只能从已经通过验证的会话中访问该功能。
(3)不要以任何方式直接提供用户名,也不要使用隐藏表单字段或者Cookies提供用户名。
(4)为了防止攻击者通过会话劫持漏洞、跨站点脚本,或者是忘记关闭的页面获得未授权访问,应该要求用户重新输入现有密码。
(5)为了防止输入错误,新密码要输入两次,顺便校验两次密码是否一致。
(6)如果是重要的系统,多次使用失败的使用密码修改功能,很有可能被攻击。
2.防止滥用“密码找回”的基本要求
密码找回可能是现在最容易出现漏洞的地方。
(1)加一个简单图片验证码,基本确保是人在操作,而不是机器。
(2)当用户遗忘密码时,需要重要的系统,最好是通过非常规的方式完成密码找回,如给呼叫中心打电话,通过发送传统邮件提供最新的验证信息,或者自动冻结一段时间。
(3)短信、邮件等方式都有可能造成漏洞,但是这个是现代互联网经济的基石。如果手机丢失了,要及时绑定新手机。
(4)不要使用任何的密码“暗示”,攻击者可以利用明显的暗示发动攻击。
(5)不要以任何方式直接提供用户名,也不要使用隐藏表单字段或者Cookies提供用户名。
(6)找回密码的问题最好有足够的随机性,确保攻击者无法轻易猜测出来。
(7)最终,用户通过重重考验,完成了密码找回,一般是给用户发送一封重新激活URL的电子邮件。即使到了这一步,也不要透露用户以前的密码等信息。如果是生成一个新密码通过短信发给用户,也要确保这组新密码足够随机,避免让攻击者猜测到。
4.3.3 对密码设置强度进行控制
关于如何设置高强度密码,可从以下几个方面着手。
(1)从内容上看,应该是自己能够记得但他人难以联想到的信息。用同学或者同事的个人信息会比用自己的安全;同时,可选择较为隐私的纪念日或者词汇进行组合。
(2)形式上,应该至少包括以下字符类别中的三组:大写字母、小写字母、数字、非数字符号(如&_等)。同时,可以进行一些简单的记忆变化,如i变成!、字母o变成数字0、11变成2ge1(两个一)。
(3)为了便于记忆,密码应该尽量是有意义的内容,但需插入其他字符或者谐音,如“just for you”可以设置为“juST4_U”。同时可以在长度上进行拉伸,如“shezhimima”可以变成“s_he_zhi_mimA”(相隔一定间隙插入符号,并且将特定位置的字母大写),又如“mypassword”可以变成“M。Y。P。A。S。S。W。O。R。D-1”。或者可使用数学运算符号来设置密码,如“5*5+5=30? Yes! ”。
(4)此外可以对自己的密码进行安全级别区分,银行、邮箱的密码级别最高,社交网站等相对较低,论坛登录等则更低。不同级别的密码千万不要设置成一样。对于级别高的密码不仅仅要设置得相对复杂,更要注意定时修改。
普通网民面临的互联网安全风险越来越严重,在目前大多数场景还是只能依靠小小的密码保护我们的情况下,这根唯一的稻草,需要我们用心对待。
jquery实现密码强度的智能判断特效是一款非常实用的jquery特效,基本上每个有会员模块的网站都可用上,可以提示会员注册时输入的密码强度,其主要用到了keyup事件。
jquery核心代码如下:
function checkPassword(pwdinput) { var maths, smalls, bigs, corps, cat, num; var str = $(pwdinput).val() var len = str.length; var cat = /.{16}/g if (len == 0) return 1; if (len > 16) { $(pwdinput).val(str.match(cat)[0]); } cat = /.*[\u4e00-\u9fa5]+.*$/ if (cat.test(str)) { return -1; } cat = /\d/; var maths = cat.test(str); cat = /[a-z]/; var smalls = cat.test(str); cat = /[A-Z]/; var bigs = cat.test(str); var corps = corpses(pwdinput); var num = maths + smalls + bigs + corps; if (len < 6) { return 1; } if (len >= 6 && len <= 8) { if (num == 1) return 1; if (num == 2 || num == 3) return 2; if (num == 4) return 3; } if (len > 8 && len <= 11) { if (num == 1) return 2; if (num == 2) return 3; if (num == 3) return 4; if (num == 4) return 5; } if (len > 11) { if (num == 1) return 3; if (num == 2) return 4; if (num > 2) return 5; } } function corpses(pwdinput) { var cat = /./g var str = $(pwdinput).val(); var sz = str.match(cat) for (var i = 0; i < sz.length; i++) { cat = /\d/; maths_01 = cat.test(sz[i]); cat = /[a-z]/; smalls_01 = cat.test(sz[i]); cat = /[A-Z]/; bigs_01 = cat.test(sz[i]); if (! maths_01 && ! smalls_01 && ! bigs_01) { return true; } } return false; }
效果如图4-21所示。
图4-21 jquery实现密码强度的智能判断特效
4.3.4 采用多重安全机制实现多因素验证
尽管多因素身份验证和多层身份验证是有优势的,但是大多数解决方案使用相同的底层网络安全机制实现它们,这会造成问题,在安全需求严格的环境中尤其如此。例如,大多数基于Web的银行系统使用SSL/TLS或HTTPS协议(Secure HyperText Transfer Protocol)作为底层网络安全机制实现基本的两因素身份验证。
为了成功地登录这种系统,最终用户通常需要以下验证因素。
(1)提交正确的密码(所需的身份验证信息是用户应该知道的某种信息)。这是第一个身份验证因素。
(2)提交用户的ATM卡号的最后四位(所需的身份验证信息是用户拥有的某种东西)。这是两因素身份验证的第二个因素,系统假设只有用户能够看到自己的ATM卡。
在这些情况下,两因素身份验证能够提高系统的安全性。要想入侵系统,黑客不但必须猜出用户的密码,还必须获得ATM卡的号码。这听起来安全多了。但是要注意一点:对于两因素身份验证的两个因素,系统使用相同的底层安全机制(SSL/TLS/HTTPS)实现网络身份验证。这会带来几个问题:如果黑客攻破了底层安全机制本身,会怎么样?如果黑客在安全机制中发现了一个漏洞,让他可以破解身份验证,而不需要了解用户的身份验证信息,会怎么样?如果有人利用安全机制的某些未知的限制破解了它,会怎么样?因为两因素身份验证的两个因素使用相同的底层安全机制实现网络身份验证,双重身份验证的优势完全被抵消了。这会带来风险,对于需要非常安全的解决方案的系统,这可能是很严重的问题。
为了解决这个问题,这里推荐一种方法。实现多因素身份验证的系统应该对不同的因素使用不同的底层安全机制,这会显著降低风险。例如,如果两因素身份验证的第一个因素使用Kerberos作为底层网络安全机制,第二个因素使用LIPKEY(一种使用SPKM的Low Infrastructure Public Key Mechanism, RFC 2847)或NTLM(NT LAN Manager,一种Microsoft身份验证协议)作为底层网络安全机制,那么黑客必须破解两种完全不同的安全机制,这加大了入侵的难度,降低了风险。这种方法通过降低风险增强了系统的总体安全性。对于实现多层身份验证的系统,也是如此。
可以使用GSS-API实现多因素身份验证,从而实现使用多种安全机制的多因素身份验证。这种技术组合可以降低使用相同底层安全机制实现多因素身份验证解决方案的风险。通过使用GSS-API,系统可以对多因素身份验证的不同因素使用不同的底层安全机制。只需在GSS-API握手过程中指定适当的与机制相关的对象标识符(OID),就可以显式地声明应用程序对于身份验证使用的底层安全机制。例如,在实现两因素身份验证的系统中,对于第一个身份验证因素,开发人员可以向GSS-API传递一个特定的安全机制OID(如Kerberos);身份验证成功之后,再用另一个安全机制OID(如LIPKEY)发起用于第二个身份验证因素的GSS-API身份验证握手。因为Kerberos机制(基于纯粹的对称密钥技术)和LIPKEY机制(基于对称和非对称密钥技术)很不一样,黑客很难同时破解这两种机制。因此,这种系统降低了使用单一安全机制实现两因素身份验证的风险。
图4-22说明了如何使用GSS-API框架为两因素身份验证显式地指定两种不同的安全机制,从而为UNIX系统提供更安全的身份验证。要想入侵这样的系统,黑客必须破解两种完全不同的安全机制而不是一种,因此提高了安全性。
图4-22 GSS-API框架为两因素身份验证显式地指定两种不同的安全机制