GB/T34944-2017 《Java语言源代码漏洞测试规范》标准是软件测试实验室开展代码测试活动的重要依据,也是软件测试实验室申请代码测试CNAS/CMA实验室认证时所依据的标准方法。本系列文章一起解读GB/T34944-2017 《Java语言源代码漏洞测试规范》,前面的文章中做了整体解读以及行为问题、路径错误、处理程序错误、不充分的封装、时间和状态方面、Web 问题、数据处理和用户界面错误方面的解读,本文继续解读安全功能部分。
6.2.6安全功能
6.2.6中分的类别比较多,一共有19类,大致可以分成5类,口令相关的、身份鉴别相关的、敏感信息相关的、密码学相关的、反控制相关的。
一、口令相关
6.2.6.1 明文存储口令
漏洞描述:
将口令明文存储。
漏洞风险:
明文存储口令会降低攻击的难度,攻击者若获得访问口令存储文件的权限,便可轻易获取口令。
修复或规避建议:
尽量避免在容易受攻击的地方存储口令。如果需要,考虑存储口令的加密散列,以替代明文口令存储。
这个很简单就不展开了讲了,大家一看就明白。
6.2.6.2 存储可恢复的口令
漏洞描述
采用双向可逆的加密算法加密口令并将口令存储在外部文件或数据库中。
漏洞风险:
攻击者有机会通过解密算法对口令进行解密。
修复或规避建议:
当业务不需要取已存储的口令进行还原时,使用单向加密算法对口令进行加密并存储。
存储可恢复的口令,与上面是类似的,就是在加解密的算法中,采用双向可逆的加密算法,加密算法加密口令并将口令存储在外部文件或数据库中。因为是双向可逆的,一旦攻击者拿到我们的算法并且拿到密钥之后,是能够解密的。
很多系统的责任方或者开发方有时候会困惑,很多时候已经把口令、敏感信息都加密了,都存在库里了,为什么还能被拿到一些重要数据?攻击者都是有非常丰富的开发经验的,并不是拿来工具随便扫描一下。他如果拿到源代码,会去分析,如果拿到程序会去逆向,能找到你在哪里做了加密,这个密钥是从哪里来的,然后找到密钥。为什么现在大家都说硬的加密方式会比软的加密方式要安全?硬的密码产品,它的机制就决定了密钥是封装在很安全的区域当中,每次调用都会生成很不一样的密钥。软的加密方式就很容易受到源代码分析的挑战。
6.2.6.3 口令硬编码
漏洞描述:
程序代码(包括注释)中包含硬编码口令。
漏洞风险:
攻击者可以通过反编译或直接读取二进制代码的方式获取硬编码口令。
修复或规避建议:
使用单向加密算法对口令进行加密并存储在外部文件或数据库中。
口令硬编码就不讲了,非常简单,这也是能力验证和测量审核过程中送分的一类内容。当然硬编码复杂程度是另一个问题。
6.2.6.13 没有要求使用强口令
漏洞描述:
软件没有要求用户使用具有足够复杂度的口令。
漏洞风险:
攻击者可以很容易地猜出用户的口令或实施暴力破解攻击。
修复或规避建议:
要求用户使用具有足够复杂度的口令。口令强度策略应包含下列属性:
最小和最大长度;
包含字母、数字和特殊字符;
不包含用户名;
定期更改口令;
不使用用过的口令。
现在其实对什么叫复杂口令已经没有明确的边界了,现在攻击和算力都很强,所以标准中给出的定义是业务场景下的一个定义,判断代码中使用的口令是不是符合。
6.2.6.14 没有对口令域进行掩饰
漏洞描述:
用户输入口令时没有对口令域进行掩饰。
漏洞风险:
增加了攻击者通过观察屏幕获取到口令的可能性。
修复或规避建议:
用户输入口令时对口令域进行掩饰。通常,用户输入的每一个字符都应该以星号形式回显。
口令的掩饰这个其实也是比较早了,现在基本上很多开发框架都不太容易这样。
二、身份鉴别类
6.2.6.4 依赖 referer 字段进行身份鉴别
漏洞描述:
依赖 HTTP 请求的 referer 字段进行身份鉴别。
漏洞风险:
攻击者可通过修改 HTTP 请求的 referer 字段冒用其他用户的身份。
修复或规避建议:
通过用户名口令、数字证书等其他手段对用户身份进行验证。
HTTP 请求里面有 referer 这个字段,有很多程序文件是拿这个来判断来源是不是合法。大家如果做过CTF这类题目的都知道,有好多题目都是让你用referer去绕过程序的判断。有些系统里面就只判断你来的上一个页面的referer是哪里,对得上的话,我就放你过去。这会产生什么问题呢,HTTP 这种协议在中间是可以截获代理去重发的,重发的时候我只要塞上一段referer就能过了,就能到达目标了。标准里正确的做法是不能用referer的方式,要用用户名和口令的方式。但这也不是唯一的好的方式,在现在口令的方式也是比较弱的,但是相对referer 的方式还是强很多。
6.2.6.11 安全关键的行为依赖反向域名解析
漏洞描述:
通过反向域名解析获取 IP 地址的域名,,然后依赖域名对主机进行身份鉴别。
漏洞风险:
攻击者可通过 DNS 欺骗修改 IP 地址与域名的对应关系,从而绕过依赖域名的主机身份鉴别。
修复或规避建议:
通过用户名口令、数字证书等其他手段对主机身份进行鉴别。
安全关键的行为依赖反向域名解析。很多程序用DNS 的方式来验证主机身份,但是 DNS 也会欺骗。
6.2.6.15 依赖未经验证和完整性检查的 cookie
漏洞描述:
应用程序当执行安全性非常重要的操作时,依赖 Cookies 的存在或它的值,而又没有正确地保证这些设置对相关的用户是有效的。
漏洞风险:
攻击者可以很容易的在浏览器中或浏览器外的客户端代码修改 cookie。依赖未经验证和完整性检査的 cookie 可以允许攻击者绕过验证,执行像 SQL注入这样的注人攻击和跨站脚本攻击或者以不期待的方式修改输人。
修复或规避建议:
在做一个安全相关的决定时,依赖服务器端存储的数据,避免依赖客户端传过来的 Cookie 数据。
依赖未经验证和完整性检查的 cookie,这个是从已有的cookie当中去读取值以后,来判断它是不是能用。 cookie在用户本地确实是可以被篡改的,所以建议要做服务器端的一个数据校验,来避免客户端传过来的 cookie的伪造和攻击。标准中举的例子是有些cookie在本地传完之后,被人分析出来,不管是加密的还是明文的。
三、敏感信息类
6.2.6.5 Cookie 中的敏感信息明文存储
漏洞描述:
敏感信息在 cookie 中明文存储。
漏洞风险:
攻击者有机会通过读取 cookie 获取敏感信息。
修复或规避建议:
将需要存储到 cookie 中的敏感信息先加密后再存储。
Cookie中的敏感信息明文存储。在 Cookie中明文存储的一些地址、用户的敏感数据等等,建议还是将Cookie中的敏感信息先加密后再存储。
6.2.6.6 敏感信息明文传输
漏洞描述:
敏感信息在传输过程中未进行加密
漏洞风险:
攻击者有机会通过在传输过程中截取或复制报文获取敏感信息。
修复或规避建议:
发送敏感信息前对敏感信息进行加密或采用加密通道传输敏感信息。
敏感信息明文传输主要讲的是http和https,在信息的传输过程中,如果没法走证书,走http形式的时候,最好要把关键的字段做加密。当然你如果用https加密协议的话会更好。
6.2.6.17 HTTPS 会话中的敏感 cookie 没有设置安全属性
漏洞描述:
HTTPS 会话中的敏感 cookie 没有设置安全属性。
漏洞风险:
若没有设置安全属性,敏感 cookie 可通过 HTTP 会话以明文形式发送,可能敏感 cookie被攻击者窃取。
修复或规避建议:
设置 HTTPS 会话中的敏感 cookie 的安全属性。
HTTPS 会话中的敏感 cookie 没有设置安全属性。HTTP 是明文的,但是HTTPS是加密的这个大家都知道。HTTPS加密之后,如果cookie 不去设置一个安全属性,叫secure,在某些情况下,攻击者可以通过HTTP 的协议去读取HTTPS下面的 cookie。这个属性主要是让cookie只能够通过HTTPS来读取。因为cookie是有同源策略的,通过明文的协议去读取加密的协议的cookie,所以要设置secure属性。
四、密码学相关
6.2.6.7 使用已破解或危险的加密算法
漏洞描述:
软件采用已破解或自定义的非标准加密算法。
漏洞风险:
使用已破解或非标准的加密算法是很危险的,因为攻击者有可能会破解算法,从而窃取所保护的数据。
修复或规避建议:
采用目前加密领域中加密强度较高的标准加密算法。
使用已破解或危险的加密算法,这个标准中举的例子是DES算法。DES算法也是一个很早、十多年前就被证实是不安全的算法,要用一些更高强度的加密算法来保护你的数据。
6.2.6.8 可逆的散列算法
漏洞描述:
软件采用的散列算法具有可逆算法,该算法可利用生成的散列值确定原始输入,或者可以找到一个输人产生相同的散列值。
漏洞风险:
攻击者可通过逆向算法获取原始输入或产生相同散列值的输人,进而绕过依赖散列算法的安全认证。
修复或规避建议:
采用当前公认的不可逆标准散列算法。
可逆的散列算法这个标准中写的有点问题,其实散列算法是不可逆的。这里的"可逆"是想表达散列的算法有点弱,但是它其实不是一个可逆的过程。大家如果做过一些散列的碰撞、破解或者彩虹表攻击,就应该知道它是从结果去反推,不是一个逆向的过程。大概是想表达这样一个意思,不要去用大家已经证实可以去做碰撞攻击、彩虹表攻击等的一些散列算法。
6.2.6.18 未使用盐值计算散列值
漏洞描述:
软件针对口令等不应可逆的输入使用了单向加密散列,但未使用盐值。
漏洞风险:
如果未使用盐值计算散列值,攻击者就更容易利用彩虹表等字典式攻击技术破解口令。
修复或规避建议:
使用盐值计算散列值,增加攻击者破解口令的难度。
未使用盐值计算散列值这个也是类似。很多散列算法,如果你输入的内容是一样的,输出的结果也一样。这就会容易出现什么情况呢,从攻击的角度来看,如果拿到很多批量的哈希值的时候,可以去猜这个是不是常用的口令。我们会发现,很多系统做完之后,口令和某些敏感字段都是一样的。这种就是没有使用盐值加一些干扰。如果我的哈希值123456跟你的123456哈希值不一样,这样就会给攻击者造成很大的困扰,提高他的攻击成本。
6.2.6.9 密码分组链接模式未使用随机初始化矢量
漏洞描述:
密码分组链接模式使用的初始化向量不是一个随机数。
漏洞风险:
攻击者有机会通过字典式攻击读取加密的数据。
修复或规避建议:
密码分组链接模式使用随机的初始化向量。
密码分组链接模式未使用随机初始化矢量,这个指的是AES算法里面有固定的初始化向量iv,在攻击当中,这个iv如果不去做随机化的话,如果写死的话,AES相当于没怎么起作用。我们现在看到很多大的互联网应用、甚至部委的有些接口也是。能从app的js接口中,找到这个iv。虽然iv被写到某一个很隐蔽的脚本里面,写死了,做了一些混淆,但是这些混淆对攻击者来说都不是问题。混淆解除之后,看到的iv是固定的,解密的过程就非常方便了。其实iv就是它初始化密钥的一部分。标准中举的例子中,大家可以看到这个加密的函数当中就是key加ips,ips是通过iv产生的,iv如果固定的话,这个加密程序就相当于是失效了。
6.2.6.10 不充分的随机数
漏洞描述:
软件在安全相关代码中依赖不充分的随机数。
漏洞风险:
攻击者可以预测将生成的随机数,绕过依赖随机数的安全保护。
修复或规避建议:
使用目前被业界专家认为较强的经过良好审核的加密 PRNG算法,初始化随机数生成器时使用具有足够长度且不固定的种子。
不充分的随机数。随机数的质量是有标准的,大家有测过随机数的话都知道有国家的相关标准,它会考察随机数产生几亿个之后,是不是具有抗分析性、抗预测性。语言中都有一些随机数生成器,像java当中的random。规范用法是建议用security,安全程度会高一些。不过还是比不上通过硬件的方式产生的随机数。
6.2.6.19 RSA 算法未使用最优非对称加密填充
漏洞描述:
使用 RSA加密算法时未使用最优非对称加密填充。
漏洞风险:
未使用最佳非对称加密填充将降低攻击者解密的难度。
修复或规避建议:
使用RSA加密算法时使用最优非对称加密填充。
RSA 算法未使用最优非对称加密填充。这个主要是RSA算法的填充方式有多种,安全机制都不太一样,建议大家使用最优的方式。标准当中也给出了举例。
五、控制类
6.2.6.12 关键参数篡改
漏洞描述:
软件未经验证使用可能被篡改的关键参数(如资产数据等)。
漏洞风险:
某些数据如页面隐藏域字段,Cookie,URL 等外部渠道传人的关键参数可能被恶意的浏览器插件、代理服务器等方式篡改。若程序获取该类数据后不经验证直接使用,可能造成信息泄露、数据异常、系统故障等安全事件。
修复或规避建议:
将关键参数缓存到服务端的会话中,程序使用该数据须通过会话获取。
关键参数篡改这个大部分是基于一些接口的,接口或函数当中的关键参数可能会被篡改。接口或函数当中的关键参数被篡改后导致业务逻辑出现问题。举的例子是,一个订单的0元购,参数没有去做校验。前些年有些互联网平台也出现过,劫取包之后,直接把价格改成0元或1分钱,也是可以下单的。为什么金融行业的相关要求高,主要是因为涉及到钱,攻击驱动力强,所以一般会加很多措施,对关键参数形成基于数字签名的一些哈希值,这个是很难破的。像现在大家用的互联网支付,支付宝等,还是有很多这种关键参数的保护在里面的。
6.2.6.16 通过用户控制的 SQL关键字绕过授权
漏洞描述:
软件使用的数据库表其中包括了某个用户不应有权访问的记录,但该软件执行的一个SQL语句中的关键字却可以受该用户控制。
漏洞风险:
如果用户可以将关键字设置为任何值,那么该用户就可以修改该关键字指向未经授权的记录。
修复或规避建议:
对用户输人的关键字进行验证,确保其只能访问该用户有权访问的记录。
通过用户控制的 SQL关键字绕过授权,这个在原理上有点类似SQL注入,就不展开讲了。
以上内容就是GB/T34944-2017 《Java语言源代码漏洞测试规范》中安全功能部分内容的解读。如需CNAS实验室认证软件测试技术培训资料、代码测试工具等方面的资料,可私信我获取。
(谢绝转载,更多内容可查看我的专栏)