• 沒有找到結果。

API Abuse (Java)

Handling (SEH) frame FS:[0x18] 4 Thread Environment

IX. SQL Injection

4.1.10 API Abuse (Java)

(1) Code Correctness: toString on Array

此漏洞發生的原因是 toString()在陣列上受到呼叫。

在程式碼中,於陣列上呼叫 toString()表示程式設計者有意將陣列內容作為 字串回傳。不過,在陣列上直接呼叫 toString(),將會回傳記憶體陣列中和雜湊 碼的字串值。

String[] strList = new String;

...

System.out.println(strList);

通常為了便輸出,當 toString()此函數在遇到 println 之類的輸出函式時,

toString()便會自動調用而不用撰寫於程式中。

故已上程式碼若輸出[Ljava.lang.String;@1232121,則可能將許多隱私的資 訊外洩。

其解決方法是針對陣列內,最後的字元定要將其定義為’\0’,故在調用到 toString()函數時,便不會洩漏隱私資料。

(2) Immutable Calsses: Non-final Fields

此類別(class)已註解為可變,但其欄位並非為 final。

此漏洞主要是程式設計者撰寫錯誤而發生。此類別已從 JCIP 註解封包 (package)加上不可變的註解。但是非 final 欄位允許此值被變更,因而違反該類 別的不可變性。

@Immutable

public class ImmutableInteger {

137

public int value;

… }

以上是不可變 final 類別的程式片段,被程式設計者錯誤地宣告欄位為 public,

而不是 final。

其解決方法是程式設計者必頇遵守程式設計的原則,否則易發生此類漏 洞。

(3) J2EE Bad Practice: getConnection()

J2EE 標準(standard)禁止直接連線管理。

J2EE 標準要求應用程式使用容器(container)的資源管理工具來取得資源連 線。

ctx = new InitialContext();

datasource = (DataSource)ctx.lookup(DB_DATASRC_REF);

conn = datasource.getConnection();

J2EE 應用程式應該以上述方式取得資料庫連線,並且應避免使用下列方式 取得連線。

conn = DriverManager.getConnection(CONNECT_STRING);

每一個主要的網路應用程式容器都會提供集中(pooled)資料庫連線管理,並 將其作為資源管理架構的一部分。在應用程式中複製此功能是困難且易出錯的,

因此 J2EE 標準便禁止此行為。

解決方法中,程式設計者應以 J2EE 標準所設定的行為而使用容器。

(4) Object Model Violation: Just One of equals() and hashCode() Defined

類別只覆寫(override)equals()或 hashCode()其中一個。Java 物件被預期地會

138

遵守數個等式(equality)相關的不變量(invariant)。其中一個不變量是相等的物件 必頇有相等的雜湊碼(hash code)。故 a.equals(b) = = true 則 a.hashCode() = = b.hashCode()。

若沒有堅持此不變性質,當此類別的物件儲存在集合(collection)中時,可能 會造成一些問題。如果此類別中的物件在雜湊表(hash table)中作為關鍵值(key),

或是把它們插入至地圖(Map)或設定(Set)中,那麼相等(equal)物件有相等的雜湊 碼是很重要的。

public class halfway() {

public boolean equals(Object obj) { ...

} }

以上的類別替換了 equals(),但是沒有替換 hashCode()。

其解決方法是遵守設計原則,相等的物件必頇有相等的雜湊碼。

(5) Uncheck Return Value

忽略函式的回傳值(return value)會導致程式忽略無法預期的狀態與情形。

Java 程式設計師經常會忽略 read()以及許多 java.io 類別函式的回傳值。Java 中大多數的錯誤以及不尋常的事件都會導致例外(exception)被丟出。

若僅部分的資料可被使用,串流(stream)與讀取器(reader)類別不會認為此為 不尋常或例外現象,並只會將部分資料加入回傳緩衝區(buffer),接著回傳讀取 位元組或字元數。

因為不能保證回傳的資料量等於要求的資料量,故程式設計師必頇檢查從

139

java.io 類別函式回傳的值,並確保能夠收到預期的資料數量。

FileInputStream fis;

byte[] byteArray = new byte[1024];

for (Iterator i=users.iterator(); i.hasNext();) { String userName = (String) i.next();

String pFileName = PFILE_ROOT + "/" + userName;

FileInputStream fis = new FileInputStream(pFileName);

fis.read(byteArray); // the file is always 1k bytes fis.close();

processPFile(userName, byteArray);

}

以上程式在一組使用者中循環(loop),讀取每個使用者的私人資料檔案。程 式設計師假設檔案大小剛好是 1KB,因而忽略了來自 read()的回傳值。如果攻擊 者可以建立更小的資料,那麼程式會回收前一個使用者剩餘的資料,並將這些 資料當作攻擊者的資料來處理。

其解決方法針對回傳值,對於每個函式的回傳值一定要做驗證,確保每個 函式皆有滿足程式設計者本身之需求,以避免例外產生卻沒有對應的解決方 法。

140