Java安全编码指南的笔记
阅读Secure Coding Guidelines for Java SE时的笔记。
FUNDAMENTALS
Guideline 0-0 / FUNDAMENTALS-0: Prefer to have obviously no flaws rather than no obvious flaws
尽可能消除缺陷。
Guideline 0-1 / FUNDAMENTALS-1: Design APIs to avoid security concerns
Guideline 0-2 / FUNDAMENTALS-2: Avoid duplication
老生常谈,项目中应当消除重复代码和重复数据,相同用途的代码和数据,应当只保留一份。
重复出现的代码,有助于提高程序员的产出,但同样引入了很多无形的工作,比如验证的工作、修改bug的工作等。
对于后来的开发者,在项目中遇到很多功能、近似的代码,将无从下手,不知该如何是好。
Guideline 0-3 / FUNDAMENTALS-3: Restrict privileges
合理控制代码的运行时权限。
Guideline 0-4 / FUNDAMENTALS-4: Establish trust boundaries
构建信任边界。
数据跨越信任边界时,需要执行必要的校验和验证。
数据在信任边界之间传输时,需要采用安全传输通道,同时执行必要的完整性、一致性等检查。
Guideline 0-5 / FUNDAMENTALS-5: Minimise the number of permission checks
通过良好的设计和实现,精简权限检查的数量。
Guideline 0-6 / FUNDAMENTALS-6: Encapsulate
良好的设计和实现,通过封装来保护数据,规避意外或者恶意的访问。
比如定义Java Bean时:
- 提供getter/setter方法来访问成员。
- 对于容器类的成员,避免暴露成员的引用。
Guideline 0-7 / FUNDAMENTALS-7: Document security-related information
完善API的文档,提供安全相关的说明,比如:
- 调用API需要具备的权限。
- 涉及安全的相关异常。
- 调用API时的注意事项,比如前置条件、调用后的清理操作等。
- API可能抛出的异常,以及对应的场景。
Guideline 0-8 / FUNDAMENTALS-8: Secure third-party code
及时更新项目中使用的第三方软件包的版本,获取其安全更新,依据其安全方面的建议,更新当前项目的配置,持续看护项目的安全性。
记忆里,有一些开源软件引入了大规模的整改工作,比如:
- Struts2
Apache Struts is a free, open-source, MVC framework for creating elegant, modern Java web applications. It favors convention over configuration, is extensible using a plugin architecture, and ships with plugins to support REST, AJAX and JSON.
- fastjson
Fastjson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. Fastjson can work with arbitrary Java objects including pre-existing objects that you do not have source-code of.
FASTJSON 2.0.x has been released, faster and more secure, we recommend you upgrade to the latest version.
Denial of Service
拒绝服务,指的是受攻击的服务,无法响应系统的友好客户发起的请求。
常见的表现,比如:
- 大量的恶意攻击,直接导致服务集群中的主机下线,从而无法提供服务。
- 大量的恶意攻击,挤占了服务集群中主机的硬件资源,比如CPU、内存、存储、网络带宽等
- 导致无法响应友好客户的请求。
- 导致响应友好客户的请求过程中,消耗的时间或者资源超出预期。
- 正常的业务请求,但触发了应用软件中的问题
- 导致无法正常响应其他友好客户的请求。
- 导致响应友好客户的请求过程中,消耗的时间或者资源超出预期。
Guideline 1-1 / DOS-1: Beware of activities that may use disproportionate resources
一些对资源使用量超出预期的行为,比如:
- 超大的图片。
- 整型数据,运算溢出类的现象。
- zip文件炸弹。
- XML解析时,处理内部实体、外部实体时引入的问题。
- 使用XPath解析XML时,消耗过多CPU时间。
- 使用Hash表时,同一个hash值映射到数量众多的value,导致访问的时间成本从常数上升为N平方。
- 正则表达式,不恰当或者错误的使用方法,导致过多的backtrack。
- Java的反序列化技术,可能消耗过多的CPU时间,或者占用过多的内存。
- 输出日志时,不恰当的日志级别,输出的对象过大,或者输出量过多,可能导致日志框架占用过多的资源,产生大量的日志文件。
- 代码中存在的循环,退出条件存在瑕疵,可能出现过高的循环次数或者死循环,从而占用过多的CPU资源,以及其它资源。
- 加载恶意代码时,恶意代码中的行为可能导致应用软件占用过多的系统资源。
处理外部输入的资源时,应当依据业务特点,完善输入数据的验证和校验,尽可能提前拦截异常数据。
前期加强对数据有效性的校验,可以降低后期应用软件在生产环境出现问题的可能性。
Guideline 1-2 / DOS-2: Release resources in all cases
系统资源,比如锁、内存、文件的输入和输出流、网络的输入和输出流等,使用完毕之后需要及时关闭,保证资源没有泄漏。
Guideline 1-3 / DOS-3: Resource limit checks should not suffer from integer overflow
关注代码中存在的整型数值的运算,消除运算溢出对应用软件的影响。
Guideline 1-4 / DOS-4: Implement Robust Error/Exceptions handling for services
Java的Exception是语言层面提供的特性,在构建应用软件时,架构师团队应当定义统一的使用和处理规范,指导开发团队采用一致的方式使用Exception。
Confidential Information
系统的关键数据,应当受限使用,控制暴露的范围。
Guideline 2-1 / CONFIDENTIAL-1: Purge sensitive information from exceptions
Java的Exception对象可能携带了敏感数据,比如文件路径,对于恶意攻击者,可以构建不同的业务请求,多次尝试之后,逐步猜测应用软件所在安装目录或者主机系统的布局。
Java的Exception对象包含了调用栈,相关信息假如暴露给恶意攻击者,可以从栈信息中推测当前应用软件使用的软件和技术,从而采用更有针对性的攻击方法,提升攻击的效率。
Guideline 2-2 / CONFIDENTIAL-2: Do not log highly sensitive information
日志仅用于跟踪业务的关键逻辑,方便定位问题,避免在日志记录系统的关键数据、敏感的数据。
Guideline 2-3 / CONFIDENTIAL-3: Consider purging highly sensitive information from memory after use
对于Java语言而言,Java对象的回收由JVM控制,因此无法像使用C/C++语言时通过回收内存的方式来清理关键信息。因此尽可能缩小关键数据、敏感数据在内存中存在的时间窗,仅在需要的时候获取数据。
Injection and Inclusion
Guideline 3-1 / INJECT-1: Generate valid formatting
Guideline 3-2 / INJECT-2: Avoid dynamic SQL
使用SQL访问DB时,注意对输出参数执行必要的转义操作。
Guideline 9-16 / ACCESS-16: Limit package accessibility with package.access
Appendix A: Defensive use of the Java Native Interface (JNI)
JNI-1: Only use JNI when necessary
非必要的情况下,仅使用Java代码和Java生态中的软件来交付业务。
以个人经历看,这个规则可以应付绝大多数业务交付场景,直到我参与机器学习业务之后,发现在这个新兴的领域,单纯依赖Java并不能独立交付业务,底层推理、训练的代码依赖GPU,目前Java生态并没有提供很好的支撑,因此需要通过JNI技术来集成相关库和代码,支撑业务交付工作。
JNI-2: Be aware of the C/C++ threat model
Java代码通过JNI技术来集成本地代码比如C/C++实现的特性。
Java语言在设计时限定了开发者的行为,和C/C++相比,一方面降低了开发者的自由度,另外一方面降低了对开发者的要求,避免开发者犯一些错误。
开发者在开发、维护本地代码时,需要关注语言层面的差异,针对性实施必要的质量保障措施。
JNI-3: Expect that JNI code can violate Java visibility and isolation rules
在本地代码中可以访问系统资源,比如内存、文件、网络sockets、线程、锁、信号量等,这些资源的生命周期由开发者管理,不受Java代码、JVM的控制。
因此在使用JNI技术时,开发者需要投入额外的精力来验证本地代码的质量。
JNI-4: Secure your JNI implementation from the Java side
在Java代码调用本地代码时,针对调用参数,注意在Java代码中增加必要的校验,提前发现非法参数,避免引发本地代码中的异常表现。
JNI-5: Properly test JNI code for concurrent access
对于可能在多线程环境下被访问的本地代码,在设计、开发、测试时,均应增加必要的考虑,避免本地代码相关的业务特性在生产环境变更上线后,出现意外的问题。
JNI-6: Secure library loading
加载JNI本地代码的方法,如下:
System.loadLibrary("/com/foo/MyLib.so");
推荐在安全可信任的代码中加载本地代码,调用本地代码中的函数。
谨慎使用RPATH或者RUNPATH。关闭RPATH的方法,见GCC安全编译选项
GCC安全编译选项。
我个人更加倾向于使用LD_LIBRARY_PATH。
JNI-7: Perform input validation at the language boundary
老生常谈,在实现JNI函数时,注意校验参数的有效性,避免无效数据穿越语言边界,引发未知、未定义的行为。
JNI-8: Expect and handle exceptions when calling from JNI into Java
本地代码不支持Java的Exception,因此在本地代码中访问Java的相关类和函数时,假如触发了Java的Exception,此时并不能自动改变本地代码的运行逻辑,Java的JNI技术提供了方法,便于开发者手工检查是否出现了Exception,进而执行必要的恢复操作。
JNI-9: Follow secure development practices for the native target platform
基于JNI技术构建本地库时,可以参照GCC安全编译选项
GCC安全编译选项
补齐相关选项,借助平台的力量,提升本地代码的安全性。
JNI-10: Ensure that bundled JVMs and JREs meet Java's secure baselines
发布版本时携带JDK或者JRE,将其作为交付件的一部分,此时开发者需设计必要的更新方案,用于及时升级JDK或者JRE的版本,升级计划与Oracle官方保持一致,及时消除潜在的安全风险。
另外,为了简化JDK或者JRE时涉及的工作,提高升级的工作效率,因此Oracle推荐开发者应当避免对JDK或者JRE内的文件进行定制修改。
本文来自博客园,作者:jackieathome,转载请注明原文链接:https://www.cnblogs.com/jackieathome/p/18419549

浙公网安备 33010602011771号