2. 认证防护
对于一个WEB系统,一般都是通过注册用户,然后用注册的信息登录系统来进行认证的。在这个过程中会需要考虑以下几点。
1)密码的强度
① 从长度上考虑
一般认为如下密码为弱密码。
l 只包含小写字母小于20个长度的密码。
l 包含各种类型字符小于10个长度的密码。
建议密码为一个句子或者几个自己熟悉的单词的组合。
② 从密码复杂性考虑
一个复杂的密码必须符合以下4个。
l 至少符合以下4个条件中3个。
Ø 包含1个以上的大写字母。
Ø 包含1个以上的小写字母。
Ø 包含1个以上数字。
Ø 包含1个以上特殊字符。
l 至少10个字符。
l 最多128个字符。
l 连续相同字符不超过2个。
以下密码是安全的:“LongLongago@thereliveaking”“1@$Smail$@1”。
以下密码是不安全的:“123456”“k222kkkkk8888”“longlongaagothereliveaking”。
③ 用户登录失败的提醒。
下面的提醒是不安全的。
l 登录失败,用户名错误(无效)。
l 登录失败,密码错误(无效)。
而应该采取以下的提示。
l 登录失败,用户名或错误(无效)。
2)忘记密码后需要采取的措施
正如第2.13-5 密码节找回所述,由于密码的复杂性,几乎所有的系统都提供密码找回功能,除了第2.13-5 密码节讲述的注意事项外,还需要掌握哪些事项呢,在这里作进一步的介绍。
l 通过向绑定的电子邮件、手机等发送验证信息,验证成功在允许修改密码。在发送验证信息时需要对绑定的电子邮件、手机进行确认。
l 回答事先设置的安全问题,一般而言必须回答对三道才可以允许修改密码。用户在设置安全问题答案需要注意保护自己的隐私。比如设置“我的手机号码是?”“你的微信登录密码是”这样类型的问题是比较傻的。
l 设置的密码最好不要与上次设置的密码相同,建议不要与最近五次设置的密码相同。
l 对每次修改密码操作进行记录。
l 保证用户在当前session内修改密码。
l 修改密码后向绑定的电子邮件、手机发送确认信息,防止他人修改。
3)凭证存储
凭证包括密码,问题的答案以及其他信息,安全存储凭证也是非常重要的。
①对凭证的字符集与长度的考虑。
限制凭证的字符集可以有效地防止SQL注入、XSS注入、命令注入等,但是也给暴力破解降低了难度。
② 使用具有密码学长度的凭证盐
维基百科中定义“在密码学中,是指通过在密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符,这种过程称之为‘加盐’”。比如用户名“Jerry”,密码为“isabell”,下面来看一下密码存储的历史。
l 明文密码存储时代。
在数据库中。
username | password |
---|---|
Jerry | isabell |
l 散列函数加密存储时代:散列函数,比如MD5 或SHA-256。
在数据库中密码使用MD5加密
username | password |
---|---|
Jerry | 7E08CF7E65BA9B02BE2A4A0D3883BFA9 |
或者密码使用SHA-256加密
username | password |
---|---|
Jerry | b66ee6cc4a06112cb18891f12d52ce1455e6719b51dc6f34a4147d27f4bfa728 |
l 加盐存储时代:对密码与盐值字符串之和采用MD5或SHA-256加密。盐值字符串是一个随机的字符串。
username | password |
---|---|
Jerry | 788924a201b9d72956d7881fda20236a1e2346a6f837ab9003f55d8f01dd3ded |
788924a201b9d72956d7881fda20236a1e2346a6f837ab9003f55d8f01dd3ded是SHA1("isabell"+"1ck12b13k1jmjxrg1h0129h2lj")。
产生的盐值需要注意以下几点。
l 盐值要针对一个凭证生成,而不是针对一个用户甚至一个系统生成。
l 要具有密码学强度的随机数生成的盐值,一般的随机数很容易被猜测,比如伪随机数。而具有密码学强度的随机数的字符串是不允许被猜测的,比如JAVA中使用SecureRandom生成的随机数,js中使用window.crypto.getRandomValues(array)生成的随机数等。
l 建议使用32字节(256位)或64(512位)字节的盐值。
l 安全方式不依赖对盐的隐藏、拆分和其他方式。
4)其他保护措施
除了上面讲到的,对于认证还需要注意以下几点。
l 密码传输最好采用SSL/TLS或其他的安全传输方式。
l 为防止DDOS攻击或CSRF注入,建议采取二次认证。
l 采用SSL/TLS客户端的强验证。
l 防止类似于暴力破解、DDOS攻击等暴力攻击,可以采用限制登录次数的方法。
l 对所有登录失败、密码错误、账户锁定操作做好有效的日志记录。
3. 会话管理安全
HTTP(S)协议是无状态的,这是受当初建立这个协议的情况而造成的。为了解决这个状态,通过Session和cookie机制来实现状态,现在几乎所有的系统都通过Session和cookie机制来管理当前的会话。一旦系统登录,就有一个SessionID的元素来控制会话。SessionID是一组键值对(Key=value)。
1)sessionID介绍
①sessionID的名称
各个语言有自己专有的sessionID名称,请见12所示。
12 各个语言的sessionID名称
语言 | sessionID名称 |
---|---|
PHP | PHPSESSION |
J2EE | JSESSIONID |
ASP.NET | ASP.NET_SessionId |
通过截获sessionID名称,可以作为使用什么开发语言的指纹信息。
② sessionID的长度
建议SessionID的长度为128位,即16个字节。
③ sessionID的熵
熵是热力学中的一个概念,表示体系的混乱程度。熵越大表示越混乱,否则表示越有序。sessionID熵属于信息熵,由信息论之父约翰·香农从热力学中借用过来的。信息熵的概念来描述信源的不确定度。一般通过随机数来增加sessionID的熵。一般要求信息熵为64位。
④ sessionID的值
sessionID的值不要包括敏感信息,并且使用SHA-256散列函数来进行加密(现在有实验表明MD5与SHA-1散列函数都是不安全的。对于MD5虽然是一种不可逆的加密方法,但是可以通过类似彩虹表rainbowcrack的工具破解。2017年3月8日Google验证SHA-1存在碰撞攻击漏洞)。
2)sessionID注意事项
使用sessionID需要注意以下四点。
l 对于sessionID的生成和验证,有宽松和严格两种方式,默认的为严格方式。但是如果程序采用宽松方式,需要做到不接受非本WEB应用程序产生的sessionID。
l 要把sessionID视为不安全的,因为sessionID可以通过GET参数、POST参数、URL 参数和HTTP头信息传输。必须对sessionID做好XSS注入等漏洞的防护工作。
l 任何权限的改动都需要更新sessionID。
l 为了降低程序的处理难度,禁止在不同的路径使用相同名称的sessionID。
3)session过期处理
session的过期分为自动过期和手动过期。
① session自动过期
自动过期又分为空闲过期、绝对过期和更新过期。
l 空闲过期:系统登录后长时间没有操作,造成session过期处理。
l 绝对过期:session超过设定好的过期时间,造成过期处理。
l 更新过期:更新系统权限,造成session过期处理。
一个安全系数高的产品应该都具有以上session自动过期处理机制。
②session手动过期
session手动过期是通过手动的方式处理session,一般包括注销登录和关闭浏览器或客户端的情况下清空session。
另外注意最好在HTTP响应头中加入Cache-Control:no-cache,no-store,pragma:no-cache,不让页面缓存session。当然也可以不对缓存内容进行黑名单处理。以下表示不允许名为session1与session2的session提供缓存。Cache-Control:no-cache="session1, session2"。
4)cookie介绍
有些网站是通过cookie管理会话机制的。采用这种方式需要注意。
l 如果采用HTTPS协议传输,必须加上Secure属性。
l 为了防止XSS注入获取信息,请在cookies中加入HTTPOnly属性。如果Cookie不使用Secure属性,并不可以保证cookie中的信息被泄露。
l 请加入SameSite属性,这样可以有效预防Cookie跨站和CSRF注入。
l 域与路径建议设置较小范围,即不设置。如果设置得比较宽,容易在同一域不同的HOST上发起攻击。
l Cookie分为持久性cookie和非持久性cookie。非持久性cookie随着session结束而自动关闭,而持久性cookie只有到指定的时间点才失效。非持久性cookie更为安全。
5)session管理防护工具
Session管理防护工具有Argon2算法、Apache Shiro 认证和Apache Shiro 会话管理几种,这里不做详细介绍,有兴趣的读者可以参考其他资料。