Fork me on GitHub

java安全编码

前言

之前在写代码的时候,就一直想过关于编码安全的问题,以及编码规范的问题。但一直没有机会去总结。
最近借了一本书看一下,名字叫Java安全编码标准。讲述了关于编码安全的内容。看了这本书后,我自己也写了点感悟和总结。

编码安全

Java语言的核心和扩展API以及JVM提供的安全特性包括安全管理器、访问控制器、加密、自动内存管理、强类型检查、字节码验证等

敏感数据泄露

在Java中,接口、类和类成员(如字段和方法)是访问受控的,这种访问受控由访问修饰符(public、private、protected、默认(package-private))来标识。
但是有一些Java平台的设计会让这种保护失效,从而导致出现安全漏洞,比如对Java反射机制的错误使用。

其中Class是当前类,Package是同一个包中的类,Subclass是子类,World是全局。

并发性

竞态条件

在大多数实际的多线程应用中,两个或两个以上的线程需要共享对同一数据的存取。如果i线程存取相同的对象,并且每一个线程都调用了一个修改该对象状态的方法,将会发生什么呢?可以想象,线程彼此踩了对方的脚。根据线程访问数据的次序,可能会产生讹误的对象。这样的情况通常称为竞态条件。

1
2
3
4
5
6
class Counter {
protected long count = 0;
public void add(long value) {
this.count = this.count + value;
}
}

假定线程A和线程B同时执行add方法,两个线程分别加了2和3到count变量上,两个线程执行结束后count变量的值应该等于5。然而由于两个线程是交叉执行的,两个线程从内存中读出的初始值都是0。然后各自加了2和3,并分别写回内存。最终的值并不是期望的5,而是最后写回内存的那个线程的值,上面例子中最后写回内存的是线程A,但实际中也可能是线程B。如果没有采用合适的同步机制,线程间的交叉执行情况就无法预料。
add()方法就是一个临界区,它会产生竞态条件。
解决方案:内置锁

volatile

volatile是一个特殊的修饰符,只有成员变量才能使用它。在Java并发程序缺少同步类的情况下,多线程对成员变量的操作对其它线程是透明的。volatile变量可以保证下一个读取操作会在前一个写操作之后发生。线程都会直接从内存中读取该变量并且不缓存它。这就确保了线程读取到的变量是同内存中是一致的。

注入

穿越受信边界的非受信数据

SQL注入

当初始的SQL查询被修改成另一个完全不同形式的查询的时候,就会出现SQL注入漏洞,执行这一被修改过的查询,可能会导致信息泄露或者数据被修改。防止SQL注入漏洞的主要方法是,净化并验证非受信输入,同时采用参数化查询的方法。

1
2
//一个用来验证用户名和密码的SQL语句
SELECT *

XML注入

「真诚赞赏,手留余香」