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