当前位置: 首页 > 工具软件 > fortify > 使用案例 >

c语言fortify扫描报告,fortify代码扫描问题结果分析

顾超
2023-12-01

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

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

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

1.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

2.Unreleased Resource

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

代码示例

Try {

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

}

Catch(Exception e) {

// Handle exception

}

Con.close();

分析

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

修正

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

3.Mutable static field

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

代码示例

public staticStringREALM;

static {

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

}

分析

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

修正

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

4.Dropped or ignored exception

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

代码示例

Try {

//handle logic

}

Catch (Exception e) { }//do nothing

分析

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

修正

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

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

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

代码示例

System.out.print

e.printStackTrace.

分析

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

修正

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

通过LOG4J等LOG工具包将信息按信息级别输出到外部系统(磁盘、数据库,甚至其它服务器比如通过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..";

}

}

6.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进行值比较

7重载方法名写错

代码示例

public int hashcode(Object o){

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

}

分析

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

8 HTTP Response Splitting

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

代码示例

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

+ fileName);

修正

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

9 其它

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

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

具体问题请参见:http://blog.sina.com.cn/s/blog_62bcc50c0100g1vi.html

 类似资料: