代码审计工具Findbugs自动检查CheckList及配置方法
代码审计工具Findbugs是一个应用比较广泛的开源代码审计工具,如果开发团队利用好了这个工具,能够很大程度上提高软件产品的安全性。而且重要的是Free。
首先,介绍一下安全审计配置文件的位置,网上都没有这方面的资料,我自己了几个小时才到。这个配置文件不在安装文件夹,也不再Eclipse软件的文件夹,而是在具体项目的工作空间workspace中,具体位置是:workspace\.metadata\.plugins\edu.umd.cs.lipse\.fbprefs。(以点开始的文件夹,还这么多层目录,很隐蔽!!!)
这个文件中,选中要审计的项目其配置值会是“TURE”,配置为不审计的项会是“FALSE”。我们可以通过在工作中逐渐确定哪些安全项一定要检查,哪些不需要检查,确定之后,整个开发团队使用同一个配置文件,从而实现标准化、自动化地审查开发团队的代码。
其次,介绍一下Findbugs的大类,为如下几种:
Malicious code vulnerability | 恶意代码 |
Dodgy | 小问题 |
Bad practice | 不好的习惯 |
Bogus random noise | 无效代码 |
Correctness | 代码的正确性 |
Internationalization | 国际化问题 |
Performance | 性能问题 |
Security | 安全性问题 |
Multithreaded currectness | 线程问题 |
Experrimental | 实验性问题 |
第三,介绍一下Findbugs的常见检查项的意思:
关键字 | 规则名 | 错误信息及建议 |
BC | BC_UNCONFIRMED_CAST | 由于没有进行类型检查, 可能会发生异常ClassCastException。推荐在类型变换前,用instanceof 来对是否可以类型变换进行检查。 |
BC | BC_IMPOSSIBLE_CAST | 因为不相关的类型之间的类型变换是不可能成功的,所以请检查相关的代码。 |
BC | DMI_RANDOM_USED_ONLY_ONCE | 在使用类java.util.Random 生成随机数。用这个类生成的随机数比较容易预测, 所以推荐用更安全的类java.security.SecureRandom。 |
Bx | DM_BOXED_PRIMITIVE_TOSTRING | 进行字段的同步的时候、得到的不是字段、而是向参照的object的lock。字段的値变化的时候、不同的线程中持有的字段的値肯定是不一样的。这个时候、不能防止同時更新。 |
Bx | DM_BOXED_PRIMITIVE_TOSTRING | 使用static 方法toString 能够提高效率,推荐使用。 |
Bx | DM_NUMBER_CTOR | 因为Number 构造函数的效率不高,推荐使用static 方法valueOf。 |
CN | CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE | switc中、有相同的code。可能只是code的重複、也有可能使oding的miss。请再检查一下code、如果是codingmiss的话、修改code、如果只是code的重複的话、为了避免重複,建议改一下code。 |
CN | CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE | 虽然定义了方法clone,但是由于没有实现接口Cloneable,推荐在类的宣言的地方,追加接口Cloneable。 |
DB | DB_DUPLICATE_BRANCHES | 不能直列化的object被保存在HttpSession中。根据 sessionobject的container、被 非活性化进而运转的话、有可能不能正常运转。所以建议修正为可以直列化的object。 |
DB | DB_DUPLICATE_SWITCH_CLAUSES | switch 中有相同的代码。可能是简单的代码重复,也可能是编码错误。推荐对该代码进行检查,如果是编码错误,修改代码,如果是代码重复,重写代码避免代码重复。 |
DB | DB_DUPLICATE_BRANCHES | 分支语句中的代码是相同的。因为代码重复,推荐删除分支语句的判断。 |
DE | DE_MIGHT_IGNORE | 有异常被捕获但是没有进行处理。 |
DLS | DLS_DEAD_LOCAL_STORE | 现在进行 方法String.indexOf()的結果大于0(>0)比較、但是 等于或者大于0(>=0)的比較又可能是对的、所以建议重新检查前後的源码。 |
DLS | DLS_DEAD_STORE_OF_CLASS_LITERAL | 不是volatile的static字段、不进行同步,被遅延初期化。Compiler以及、processor、有可能命令并排被执行、如果方法同时从複数的线程被调用的话,线程访问这个字段的时候、可能会出现可以看到被初期化了一半的instance的危险。通过 对于字段进行volatile,或者是 对于初期化bloc进行同步、可以解决这个問題。 |
DLS | DLS_DEAD_LOCAL_STORE | 局部变量被赋值,但是之后赋的值没有被使用,所以推荐不对该局部变量赋值。 |
DLS | DLS_DEAD_STORE_OF_CLASS_LITERAL | java.lang.Class 的实例被保存到局部变量。因为这个实例不会被使用,推荐删除该实例。 |
Dm | DM_BOOLEAN_CTOR | 用multi线程同時更新的时候、可能会得到予想外的結果、所以建议重新检查。 |
Dm | DM_EXIT | 因为被参照的是可能为null的object、所以建议在参照之前进行null的验证。 |
Dm | DM_STRING_CTOR | 现在是调用没有被写入的字段。有可能是codingmiss、建议重新检查関連的源代码。 |
Dm | DM_STRING_TOSTRING | (&或者|)和(&&或者||)的使用好像是弄错了。(&或者|)、一定会对于両側的公式进行評価。如果把(&&或者||)错误的使用为(&或者|)的话、不光是効率会变低、如果 运算符的左側的公式成为 为了访问右側的guard条件的话、会出现error。建议检察code进行修正,有誤用的话、请修正(&&或者||)。 |
Dm | DM_STRING_VOID_CTOR | 正規表現的文法错了。这个和 例外PatternSyntaxException的発生相关。建议重新检查正規表現的写法。 |
Dm | DM_EXIT | it 会使VM整体终了。应该只使用到必须要使用的地方。这样的code、会对再利用性造成损失。建议对RuntimeException进行throw,进行替代。 |
Dm | DM_BOOLEAN_CTOR | 使用方法valueOf()比使用Boolean 的构造函数生成Boolean 对象更有效率,所以推荐使用方法valueOf()。 |
Dm | DM_STRING_CTOR | 因为使用String(String)构造函数生成新字符串会浪费内存,推荐使用原有字符串。 |
Dm | DM_STRING_TOSTRING | 由于类型变换前后的类型都是String,所以推荐不进行类型变换。 |
Dm | DM_STRING_VOID_CTOR | 生成空字符串时使用了new String()构造函数。由于直接赋值空字符串「""」的效率较高,推荐直接赋值空字符串。 |
DMI | DMI_INVOKING_TOSTRING_ON_ANONYMOUS_ARRAY | toString将引起一个无用的结果[C@16f0472。 考虑使用String转换。 |
EC | EC_ARRAY_AND_NONARRAY | 因为数组类型的对象和非数组类型对象的比较结果肯定是false,这样的比较没有意义。推荐对相关的代码进行检查。 |
EC | EC_NULL_ARG | 传入方法equals()的参数值是null 的情况下,结果肯定是false。这种情况下,使用方法equals()没有意义。推荐检查相关代码。 |
EC | EC_UNRELATED_CLASS_AND_INTERFACE | 因为可能是编码上的错误,所以推荐检查相关代码。 |
EC | EC_UNRELATED_TYPES java生成随机数的方法 | 用方法equals 对不相关类型对象的比较结果肯定是false。这样没有意义的方法调用可能是由于编码上的错误造成的,所以推荐检查相关代码。 |
ES | ES_COMPARING_PARAMETER_STRING_WITH_EQ | 直列化可能的class中,存在非直列、并且不是transient、并且不是static的instance字段。这个class没有实现interfaceExternalizable,而且没有定义 方法readObject和writeObject、所以 直列和復元処理不能正确进行。建议重新检查関連的源代码。 |
ES | ES_COMPARING_STRINGS_WITH_EQ | 由于对象值的比较中,应该使用方法equals,所以推荐使用方法equals。 |
ES | ES_COMPARING_PARAMETER_STRING_WITH_EQ | 以「==」或者「!=」进行String parameter的比較、 比较parameter的値的时候、应该使用方法equals、所以建议修正为使用方法equals。 |
IC | IC_INIT_CIRCULARITY | 因为初始化处理中会产生死循环,所以推荐检查相关的代码。 |
IJU | IJU_SETUP_NO_SUPER | 继承了测试类和方法。设定方法应该叫super.setUp ()。 |
IL | IL_INFINITE_LOOP | 因为循环条件一直是true,所以要让循环停止只能抛出异常。推荐检查相关代码。 |
IL | IL_INFINITE_RECURSIVE_LOOP | 无条件地对自身调用。因为在这种情况下会发生死循环,所以推荐检查相关的代码。 |
IP | IP_PARAMETER_IS_DEAD_BUT_OVERWRITTEN | 在classjava.util.Random生成随机数。在这个class生成的随机数很容易予測、所以建议使用更加安全的classjava.security.SecureRandom。 |
IP | IP_PARAMETER_IS_DEAD_BUT_OVERWRITTEN | 由于对参数的修改会被忽视掉,所以推荐删除该代码。 |
ITA | ITA_INEFFICIENT_TO_ARRAY | 如果象「Array(new Foo[myCollection.size()」一样传入指定长度的数组参数内部处理中不会生成新的数组,处理效率会提高。推荐传入和变换前Collection 的大小一样的数组。 |
J2EE | J2EE_STORE_OF_NON_SERIALIZABLE_OBJECT_INTO_SESSION | HttpSession 中有无法序列化的对象。当容器移动Session 对象,或使Session 对象睡眠时,可能无法正常执行。推荐把对象修改成可序列化的对象。 |
J2EE | J2EE_STORE_OF_NON_SERIALIZABLE_OBJECT_INTO_SESSION | 向本地变量进行了代入、后面没有使用过这値、建议避开这个代入。 |
LI | LI_LAZY_INIT_STATIC | 非volatile 的static 字段在没有被同期的情况下被延迟初始化。编译器及处理器可能会把指令重新排列,所以当多线程中同时调用时,可能会出现不能正确初始化的结果。如果把字段改成volatile 或者把初始化模块同期,这个问题能够被解决。 |
LI | LI_LAZY_INIT_UPDATE_STATIC | 多线程同时更新的时候,可能会出现预想之外的结果。所以推荐检查相关代码。 |
LI | LI_LAZY_INIT_STATIC | 在类String的方法equals(),空文字列被check了、建议在方法ength(length() == 0)进行check。 |
LI | LI_LAZY_INIT_UPDATE_STATIC | 参数的変更内容、不是覆盖,只是去掉、所以建议削除。 |
ML | ML_SYNC_ON_FIELD_TO_GUARD_CHANGING_THAT_FIELD | 用字段来作为同期的锁的时候,是对这个字段参照的对 象加锁。当字段的值变化的时候,不同的线程所参照的 字段的值不一定相同。这种情况下,无法防止对字段的 同时更新。 |
ML | ML_SYNC_ON_FIELD_TO_GUARD_CHANGING_THAT_FIELD | 交给方法Array()长度为0的数组。「Array(new Foo[myCollection.size()」那样、根据指定変換源的Collection的长度、内部的処理中不生成新的数组、処理効率会提高。建议修改为把长度和変換源的Collection的size相同的数组交给方法。 |
Nm | NM_CLASS_NAMING_CONVENTION | 未使用分配的变量,建议将相应变量删除。 |
Nm | NM_CLASS_NAMING_CONVENTION | 根据一般的编码规范,类名应该以大写字符开始。推荐把第一个字符改成大写。 |
NP | NP_ALWAYS_NULL | 由于值可能是null 的对象被参照,可能会发生异常NullPointerException。推荐使用该对象前,先进行null的检查。 |
NP | NP_ALWAYS_NULL_EXCEPTION | 方法的异常处理中, null 被参照。因为异常NullPointerException 可能会发生,所以推荐修改相关的代码。 |
NP | NP_UNWRITTEN_FIELD | 没有被赋值的字段被使用。由于这可能是编码上的错误,所以推荐检查相关的代码。 |
NP | NP_TOSTRING_COULD_RETURN_NULL | toString方法在某些情况下会返回一个null,但这有可能造成其他代码被破坏。建议返回一个空字符串或者其他字符而不是null。 |
NP | NP_ALWAYS_NULL | 调用了値可能为null的局部变量,可能会例外发生NullPointerException,建议在调用前追加null检查。 |
NP | NP_ALWAYS_NULL_EXCEPTION | null可能的变量被参照、因为有例外NullPointerException発生的可能性、建议参照之前进行null check。 |
NP | NP_LOAD_OF_KNOWN_NULL_VALUE | DB接続関連的资源没有被发布。建议追加发布资源処理。 |
NP | NP_UNWRITTEN_FIELD | 例外発生時DB接続相关的资源未发布。建议将发布DB接続相关的资源的処理追加到finally中。 |
NS | NS_DANGEROUS_NON_SHORT_CIRCUIT | 位操作符(&或|)被作为布尔操作符(&&或||)误用。使用位操作符时,两边表达式的值都会被评价。当位操作符被当作布尔操作符使用时,不仅仅是效率变差,当操作符左边的表达式是右边表达式的保护条件时,会产生错误。检查相关的代码,如果是被误用,推荐修改成布尔 操作符。 |
NS | NS_DANGEROUS_NON_SHORT_CIRCUIT | 对象的参照明显不是null,建议将针对该参照的null检查删除。 |
ODR | ODR_OPEN_DATABASE_RESOURCE | 由于DB 连接相关的资源没被释放,推荐追加释放资源的处理。 |
ODR | ODR_OPEN_DATABASE_RESOURCE_EXCEPTION_PATH | 由于例异常发生时DB 连接相关资源没被释放,推荐把DB连接相关的资源释放处理追加到finally 中。 |
OS | OS_OPEN_STREAM | 一直使用的是値为null的局部变量,建议使用定量null,代替局部变量。 |
OS | OS_OPEN_STREAM_EXCEPTION_PATH | 由于例外发生时,流没被关掉,所以推荐把流关闭的处理追加到finally。 |
RCN | RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE | 只是为了调用interrupted()方法而调用Thread.currentThread()的。由于interrupted()方法是static方法,因此,建议修改为Thread.interrupted()的调用。 |
RCN | RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE | 循环中,字符串是用String连接的,但是使用StringBuffer连接更有効率,因此,建议使用StringBuffer。 |
RCN | RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE | 由于当对象是null 的情况下,对该对象的使用会导致异常NullPointerException 的抛出,推荐在对象被使用前进行null 检查。 |
RE | RE_BAD_SYNTAX_FOR_REGULAR_EXPRESSION | 正则表达式的文法错误。这会导致异常PatternSyntaxException 的抛出。推荐检查正则表达式的写法。 |
RE | RE_BAD_SYNTAX_FOR_REGULAR_EXPRESSION | 目前是使用String构造器由String对象生成新的String对象,但是,由于原来的String对象可以使用,所以,建议不生成没用的String对象,而使用原来的String对象。 |
RI | RI_REDUNDANT_INTERFACES | 被实现的接口会自动的被子类实现,所以没有必要再次定义实现。推荐删除该定义。 |
RV | RV_EXCEPTION_NOT_THROWN | 异常对象被生成后,该对象没被抛出。这可能是编码上的错误,推荐检查相关的代码。 |
SA | SA_LOCAL_SELF_ASSIGNMENT | 由于局部变量对自身赋值没有意义,所以推荐删除该语句。 |
Se | SE_BAD_FIELD | 可序列化的类中,有不能序列化,也不是transient,也不是static 的字段。并且这个类也没有实现接口Externalizable , 也没定义方法readObject 及writeObject,所以序列化及反序列化处理无法正常进行。 |
Se | SE_TRANSIENT_FIELD_NOT_RESTORED | 在方法readObject/readResolve 中transient 字段没被赋值。当对象被反序列化时,这个字段将不会初始化。推荐把字段改成非transient,或者修改成static,或者在方法eadObject/readResolve 中对该字段赋值。 |
SF | SF_SWITCH_FALLTHROUGH | switch 中有没被break 的case 语句。这种情况时,下一个case 语句也会被执行。一般的情况,用break 或return来结束case 语句。所以,推荐检查相关的代码。 |
SS | SS_SHOULD_BE_STATIC | final 字段在编译时会当成静态的值,推荐修改成staticfinal。 |
STCAL | STCAL_INVOKE_ON_STATIC_DATE_FORMAT_INSTANCE | 因为类DateFormat 不是线程安全,所以不推荐使用DateFormat 类型的static 字段,而是在需要使用这个类的地方,生成这个类的对象使用。 |
STCAL | STCAL_STATIC_SIMPLE_DATE_FORMAT_INSTANCE | 因为类SimpleDateFormat 不是线程安全,所以不推荐使用SimpleDateFormat 类型的static 字段,而是在需要使用这个类的地方,生成这个类的对象使用。 |
STI | STI_INTERRUPTED_ON_CURRENTTHREAD | 因为方法interrupted()是static,所以推荐修改成Thread.interrupted()。 |
UCF | UCF_USELESS_CONTROL_FLOW | 因为控制语句没被使用,推荐删除该语句。 |
UPM | UPM_UNCALLED_PRIVATE_METHOD | private 方法一次都没被调用,所以推荐删除该方法。 |
UrF | URF_UNREAD_FIELD | 由于字段没被读过,推荐删除该字段。 |
UwF | UWF_UNWRITTEN_FIELD | 由于字段没被写入过,所以也没被初始化。当该字段被读取时,会使用缺省值。所以推荐追加该字段的初始化处理,或删除该字段。 |
WMI | WMI_WRONG_MAP_ITERATOR | 和keySet 相比,使用entryKey 效率较高,推荐修改成entryKey。 |
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论