界: Code Quality

程式碼品質不佳,會導致無法預料的行為。從使用者的角度來看,這通常表現為可用性不佳。對於攻擊者而言,這提供了以意想不到的方式向系統施加壓力的機會。

4 找到的項目
弱點
Abstract
將位元組陣列轉換成 String 可能會導致資料遺失。
Explanation
從位元組陣列將資料轉換成 String 時,未指定任何資料超出適用的字元集時將會發生什麼情況。這可導致資料遺失,或是當需要二進位資料來確保遵循正確的安全措施時,這可導致安全等級降低。

範例 1:以下程式碼會將資料轉換成字串以建立雜湊。


...
FileInputStream fis = new FileInputStream(myFile);
byte[] byteArr = byte[BUFSIZE];
...
int count = fis.read(byteArr);
...
String fileString = new String(byteArr);
String fileSHA256Hex = DigestUtils.sha256Hex(fileString);
// use fileSHA256Hex to validate file
...


假設檔案的大小低於 BUFSIZE,只要 myFile 中的資訊編碼方式與預設字元集相同,這就可以正常運作,但是如果使用的是不同的編碼,或是這是二進位檔案,將會遺失資料。這進而會導致產生的 SHA 雜湊較不可靠,並且可能表示,比較容易造成衝突,尤其是以相同的值 (例如問號) 表示超出預設字元集的任何資料時。
References
[1] STR03-J. Do not encode noncharacter data as a string CERT
[2] When 'EFBFBD' and Friends Come Knocking: Observations of Byte Array to String Conversions GDS Security
[3] Standards Mapping - Common Weakness Enumeration CWE ID 486
desc.semantic.java.code_correctness_byte_array_to_string_conversion
Abstract
NaN 進行比較一律是錯誤。
Explanation
NaN 進行比較時,一律會估算為 false,除了 != 運算子之外,這個運算子一律會估算為 true,因為 NaN 處於未排序狀態。

範例 1:以下將嘗試確定變數不是 NaN


...
if (result == Double.NaN){
//something went wrong
throw new RuntimeException("Something went wrong, NaN found");
}
...


這會嘗試驗證 result 不是 NaN,不過使用 == 運算子搭配 NaN 一律會產生值 false,因此這項檢查永不會拋出異常。
References
[1] NUM07-J. Do not attempt comparisons with NaN CERT
[2] Java Language Specification Chapter 4. Types, Values, and Variables Oracle
[3] INJECT-9: Prevent injection of exceptional floating point values Oracle
[4] Standards Mapping - Common Weakness Enumeration CWE ID 486
desc.structural.java.code_correctness_comparison_with_nan
Abstract
根據物件的類別名稱來判定物件類型可能會導致意想不到的行為或讓攻擊者注入惡意的類別。
Explanation
攻擊者可能故意複製類別名稱,來迫使程式執行惡意程式碼。因此,使用類別名稱來識別類型並不適合,所以不應據此對特定物件授予信任。

範例 1:以下程式碼根據物件類別名稱來判斷是否信任來自 inputReader 物件的輸入。如果一個攻擊者能提供執行惡意指令的 inputReader 實作,這個程式碼將無法區分物件是否為惡意版本。


if (inputReader.GetType().FullName == "CompanyX.Transaction.Monetary")
{
processTransaction(inputReader);
}
References
[1] Standards Mapping - Common Weakness Enumeration CWE ID 486
desc.dataflow.dotnet.code_correctness_erroneous_class_compare
Abstract
根據物件的類別名稱來判定物件類型可能會導致意想不到的行為或讓攻擊者插入惡意的類別。
Explanation
攻擊者可能故意複製類別名稱,來迫使程式執行惡意程式碼。因此,使用類別名稱來識別類型並不適合,所以不應據此對特定物件授予信任。

範例 1:以下程式碼根據物件類別名稱來判斷是否信任來自 inputReader 物件的輸入。如果一個攻擊者能提供執行惡意指令的 inputReader 實作,這個程式碼將無法區分物件是否為惡意版本。


if (inputReader.getClass().getName().equals("com.example.TrustedClass")) {
input = inputReader.getInput();
...
}
References
[1] OBJ09-J. Compare classes and not class names CERT
[2] Standards Mapping - Common Weakness Enumeration CWE ID 486
desc.dataflow.java.code_correctness_erroneous_class_compare
Abstract
根據物件的類別名稱判斷物件的類型時,可能會導致意外行為,或允許攻擊者注入惡意類別。
Explanation
攻擊者可能故意複製類別名稱,來迫使程式執行惡意程式碼。因此,使用類別名稱來識別類型並不適合,所以不應據此對特定物件授予信任。

範例 1:以下程式碼根據物件類別名稱來判斷是否信任來自 inputReader 物件的輸入。如果一個攻擊者能提供執行惡意指令的 inputReader 實作,這個程式碼將無法區分物件是否為惡意版本。


if (inputReader::class.qualifiedName == "com.example.TrustedClass") {
input = inputReader.getInput()
...
}
References
[1] OBJ09-J. Compare classes and not class names CERT
[2] Standards Mapping - Common Weakness Enumeration CWE ID 486
desc.dataflow.kotlin.code_correctness_erroneous_class_compare
Abstract
靜態方法是無法取代的,但是在做為實例方法被呼叫時,可能會隱藏起來。
Explanation
靜態方法無法使用定義加以取代,因為它們屬於該類別實例以外的類別。雖然在一些案例中,似乎已在子類別中取代靜態方法,但是這可能導致衝突,並可導致要呼叫的方法的版本不正確。

範例 1:以下會嘗試定義 API 以驗證使用者。


class AccessLevel{
public static final int ROOT = 0;
//...
public static final int NONE = 9;
}
//...
class User {
private static int access;
public User(){
access = AccessLevel.ROOT;
}
public static int getAccessLevel(){
return access;
}
//...
}
class RegularUser extends User {
private static int access;
public RegularUser(){
access = AccessLevel.NONE;
}
public static int getAccessLevel(){
return access;
}
public static void escalatePrivilege(){
access = AccessLevel.ROOT;
}
//...
}
//...
class SecureArea {
//...
public static void doRestrictedOperation(User user){
if (user instanceof RegularUser){
if (user.getAccessLevel() == AccessLevel.ROOT){
System.out.println("doing a privileged operation");
}else{
throw new RuntimeException();
}
}
}
}


乍看之下,此程式碼似乎正常。但是,由於我們將針對 user 實例 (而不是針對 UserRegularUser 類別) 呼叫 getAccessLevel() 方法,因此這將意味著,此狀況一律會傳回 true,並且會執行限制的操作,即使使用 instanceof 以進入 if/else 區塊的此部分也是如此。
References
[1] MET07-J. Never declare a class method that hides a method declared in a superclass or superinterface CERT
[2] Java Language Specification Chapter 8. Classes Oracle
[3] Standards Mapping - Common Weakness Enumeration CWE ID 486
desc.structural.java.code_correctness_hidden_method