1. 程式人生 > >fortify程式碼掃描問題結果分析

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 staticStringREALM;

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 分析結果檔案。

系統安全攻擊問題

   詳見:http://download.csdn.net/detail/u011897392/9806386

具體問題請參見:http://blog.sina.com.cn/s/blog_62bcc50c0100g1vi.html