公司新闻


fortify代码扫描问题结果分析

最近项目的代码使用fortify工具扫描了一下,发现了项目中存在的一些问题,在以后代码编写的过程中要注意,避免出现类似的错误。

以下为本次代码分析工具FORTIFY对代码的分析结果。这些问题虽然古老、简单然而经典,也是需要引起重视。

代码问题主要集中在如下类别:存在安全隐患、存在资源泄漏隐患、序列化问题、字符串比较、异常处理问题,以及其它一些BAD PRACTICE和粗心引起的问题。

 

J2EE Bad Practices: Non-Serializable Object Stored in Session (Time and State, Structural)

把一个不可序列化的对象作为 HttpSession 属性来储存会破坏应用程序的可靠性。

代码示例

 

SharerInfo sharerInfo = new SharerInfo();

getServletRequest().getSession().setAttribute( “sharerInfo”, shareInfo);

其中SharerInfo类没有实现序列化(implements java.io.Serializable)

 

分析

对于不需要将对象序列化到同一jvm以外的应用场景,以上代码没有问题。然而考虑到系统的扩展性,以上问题应该予以避免。

以下是一些常见的会导致问题的场景:

1.       session对象存储到外部系统

在一些大型应用系统的实现里,会考虑将部分SESSION里的对象钝化到数据库、磁盘里。

2.       集群环境

在非session-sticky的集群环境里,应用服务器会在集群里广播、复制session数据

修正

   ShareInfo类应该实现序列化:implements java.io.Serializable

Unreleased Resource

程序可能无法成功释放某一项系统资源

代码示例

         Try {

Connection con = jdbcTemplate.getDataSource().getConnection();

     }

         Catch(Exception e) {

   // Handle exception

}

Con.close();

分析

   系统资源比如数据库资源(Connection ,Statementetc)IO资源(InputStream,OutputStream,etc)都是有限的,如果没有正确的释放掉,就会出现资源泄漏的问题。常见的后果如出现数据库连接池无可用连接(pool exhausted),Too many open files

 修正

  将资源释放代码放到finally块中进行

Mutable static field

将业务上不可变的静态值作为非final属性直接暴露给调用者

代码示例

public static  String  REALM;

 

static {

         REALM= bundle.getMessage("realm",null,DEFAULT_LOCALE);  

}

分析

  在业务上REALM是常量。但这样直接将REAM作为非FINAL静态属性暴露给调用者,容易导致静态属性值被修外部调用者修改,从而导致系统问题。

修正

   realm定义为final类型或者通过getRealm方法暴露接口,而隐藏setRealm方法。


Dropped or ignored exception

异常不做任何处理直接忽略

代码示例

  Try {

   //handle logic

  }

           Catch (Exception e) {   }//do nothing

   分析

      将异常捕获后直接忽略是一种BAD PRACTICE.

   修正

     如果需要处理异常(比如打印异常信息),则进行处理。如果不需要,则继续抛出异常给更外层的调用者

直接将信息输出到标准输出

这是一种BAD PRACTICE。严重的情况下还会对系统性能造成冲击。

代码示例

  System.out.print

e.printStackTrace.

分析

   以上是两种常见的不被推荐的打印信息的代码例子。

修正

      虽然可以通过修改系统属性或者修改System.out的输出属性来改变System.out.print等方法的输出目标。但更建议直接禁止这种写法。

   通过LOG4JLOG工具包将信息按信息级别输出到外部系统(磁盘、数据库,甚至其它服务器比如通过JMS将日志发送给日志服务器)。

如果想获取异常堆栈信息(e.printStackTrace,可以利用如下helper代码捕获整个异常堆栈信息:

  public class StackTraceUtil {

       public static String getStackTrace(Throwable exception) {

        if (exception != null) {

            StringWriter sw = new StringWriter();

            PrintWriter pw = new PrintWriter(sw);

            exception.printStackTrace(pw);

            return sw.toString();

        } else {

return "thrown exception is null.no more exception information can provide..";

}

    }

Checking String equality using == or !=

通过==而不是equals比较字符串数据。

 

代码示例

String a=”abc”

String b=”abc”;

System.out.println(a==b)

分析

 “==”是比较指针是否指向同一地址,而equals比较的是数据。事实上除了原子类型的数据外,其它大部分情况下,值比较都应该使用equals

String是个特殊情况。为了提高效率,JVM 维护了字符串池。以上代码里定义b时,b仍然指向a的指针,而不是重新分配一块内存给b.所以虽然对于a==b来说,比较的是地址指针,但a==b仍然为true.但对于如下场景 a==b将为false:

String a= “abc”;

String b= new String(“abc”);

System.out.println (a==b).

在以上代码里 new String重新为b分配了一块内存,所以结果将是false.

修正

  使用equals进行值比较


重载方法名写错

代码示例

public int hashcode(Object o){                  

return this.a.hashCode()+this.b.hashCode();

}

分析

 以上代码本意应该是想重载ObjecthashCode(Object o)方法。但不小心些错了。对于jdk5及以后的jvm,可以通过@override在编译期发现改问题。对于jdk1.4及以前的环境,只能通过小心检查来避免这种情况。不过很多IDE工具都提供对这种常见需覆盖方法(比如hashCode,equals等)的智能化完成功能。

HTTP Response Splitting

对于XSS漏洞,通常情况下通过过滤转换<,>等敏感字符来防御。但对于http response splitting(报头分离)漏洞,还应该针对回车、换行这两个敏感字符进行过滤。

代码示例

response.addHeader("Content-Disposition", "attachment; filename="

               + fileName);

修正

   如果fileName的来源不可靠,则需要过滤\13\10(回车、换行)字符

其它

其它包括一些粗心造成的代码问题。比如对Nuberm类型的数据进行如下比较:Numbera.equals(“”)等。

   以上为本次hotwarn级别的代码分析总结,具体问题代码明细见fortify 分析结果文件。


扫一扫,反馈当前页面

咨询反馈
扫码关注

微信咨询

返回顶部