程式碼品質不佳,會導致無法預料的行為。從使用者的角度來看,這通常表現為可用性不佳。對於攻擊者而言,這提供了以意想不到的方式向系統施加壓力的機會。
NaN
進行比較一律是錯誤。NaN
進行比較時,一律會估算為 false
,除了 !=
運算子之外,這個運算子一律會估算為 true
,因為 NaN
處於未排序狀態。NaN
。
...
if (result == Double.NaN){
//something went wrong
throw new RuntimeException("Something went wrong, NaN found");
}
...
result
不是 NaN
,不過使用 ==
運算子搭配 NaN
一律會產生值 false
,因此這項檢查永不會拋出異常。this
參考,這可進而導致弱點。
...
class User {
private String username;
private boolean valid;
public User(String username, String password){
this.username = username;
this.valid = validateUser(username, password);
}
public boolean validateUser(String username, String password){
//validate user is real and can authenticate
...
}
public final boolean isValid(){
return valid;
}
}
validateUser
函數和類別不是 final
,這表示它們可以被取代,然後將變數初始化為會取代此函數的子類別時,會允許規避 validateUser
功能。例如:
...
class Attacker extends User{
public Attacker(String username, String password){
super(username, password);
}
public boolean validateUser(String username, String password){
return true;
}
}
...
class MainClass{
public static void main(String[] args){
User hacker = new Attacker("Evil", "Hacker");
if (hacker.isValid()){
System.out.println("Attack successful!");
}else{
System.out.println("Attack failed");
}
}
}
Example 1
中的程式碼會列印「Attack successful!」,因為 Attacker
類別會覆寫從 User
超級類別之建構函式呼叫的 validateUser()
函數,並且 Java 會先查看子類別中是否有從建構函式呼叫的函數。inputReader
物件的輸入。如果一個攻擊者能提供執行惡意指令的 inputReader
實作,這個程式碼將無法區分物件是否為惡意版本。
if (inputReader.GetType().FullName == "CompanyX.Transaction.Monetary")
{
processTransaction(inputReader);
}
inputReader
物件的輸入。如果一個攻擊者能提供執行惡意指令的 inputReader
實作,這個程式碼將無法區分物件是否為惡意版本。
if (inputReader.getClass().getName().equals("com.example.TrustedClass")) {
input = inputReader.getInput();
...
}
inputReader
物件的輸入。如果一個攻擊者能提供執行惡意指令的 inputReader
實作,這個程式碼將無法區分物件是否為惡意版本。
if (inputReader::class.qualifiedName == "com.example.TrustedClass") {
input = inputReader.getInput()
...
}
x = NULL
與 x != NULL
將永遠為 false。NULL
的值不確定。此值沒有任何對等的值,甚至也不等於另一個 NULL
值。另外,null
值絕對不會與其他值相等。範例 2:下列陳述將永遠為 false。
checkNull BOOLEAN := x = NULL;
checkNotNull BOOLEAN := x != NULL;
equals()
方法來比較字串,而不是 ==
或 !=
。==
或 !=
來比較兩個字串是否相等,其為比較兩個物件是否相同,而非它們的值。因此,若使用這個方法,兩個參照將永遠不會相等。
if (args[0] == STRING_CONSTANT) {
logger.info("miracle");
}
==
和 !=
運算子來比較相同物件中的字串時,它們只會如預期般的運作。要出現這種情況,最常見的方法就是將字串控制在內部,這樣,將字串增加到由 String
類別維護的物件池中。一旦將字串控制在內部,每次使用這個字串時都將使用相同的物件,並且相等運算子會如預期般運作。所有字串文字和以字串當作值的常數會自動控制在內部。其他字串可以透過呼叫 String.intern()
來以手動控制在內部,這將會回傳目前字串的標準實例,必要時也會建立一個實例。