界: Code Quality

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

Null Dereference

Abstract
程式可能會解除參照 Null 指標,因此造成 NullException
Explanation
Null 指標錯誤通常是由於一個或者多個程式設計人員的假設被破解而造成的。

大部分的 Null 指標問題都會導致一般軟體可靠性問題,但是如果攻擊者蓄意觸發 Null 指標解除參照的話,攻擊者就可能會使用引發的異常來略過安全性邏輯,或是使應用程式洩漏出除錯資訊,這些資訊對於計畫後續攻擊很有價值。

範例 1:在以下程式碼中,程式設計人員假設系統永遠會定義一個名為「cmd」的屬性。如果攻擊者可以控制程式環境,使「cmd」變成未定義狀態,那麼程式會在嘗試呼叫 Trim() 方法時拋出一個 Null 指標異常。


string cmd = null;
...
cmd = Environment.GetEnvironmentVariable("cmd");
cmd = cmd.Trim();
desc.controlflow.dotnet.null_dereference
Abstract
程式可能解除參照一個 Null 指標,造成分段錯誤。
Explanation
Null 指標異常通常是由於一個或者多個程式設計師的假設遭到破解而造成的。此問題至少有三項特點:解除參照之後檢查、檢查後解除參照及儲存後解除參照。當程式在檢查指標是否為 null 之前先解除參照可能為 null 的指標,將會造成「解除參照之後檢查」的錯誤。當程式執行明確的 null 檢查,但仍繼續解除參照已知為 null 的指標時,將會造成「檢查後解除參照」的錯誤。這種類型的錯誤通常是打字錯誤或程式設計師的疏忽所造成。當程式明確的將某指標設定為 null,卻在之後解除參考該指標,則會發生儲存後解除參照錯誤。這種錯誤通常是由於程式設計師在宣告變數時將變數初始化為 null 所致。

大部分的 Null 指標問題都會導致一般軟體可靠性問題,但是如果攻擊者蓄意觸發 Null 指標解除參照的話,攻擊者就可能會使用引發的異常來略過安全性邏輯以掛載 Denial of Service 攻擊,或是使應用程式洩漏出除錯資訊,這些資訊對於計畫後續攻擊很有價值。

範例 1:在以下程式碼中,程式設計師假設變數 ptr 不是 NULL。當程式設計師取消參照指標時,這個假設就變得清楚。當程式設計師檢查 ptrNULL 時,這個假設其實就出現其矛盾之處。若在 if 指令中檢查 ptr 時,其可為 NULL,則解除參照時也可為 NULL,並產生分段錯誤。


ptr->field = val;
...
if (ptr != NULL) {
...
}
範例 2:在以下程式碼中,程式設計師確定變數 ptrNULL,並在之後以錯誤的方式解除參照。若在 if 陳述式中檢查 ptr 時,其非 NULL,就會發生 null 解除參照,從而導致分段錯誤。


if (ptr == null) {
ptr->field = val;
...
}
範例 3:在以下程式碼中,程式設計師忘記了字串 '\0' 實際上是 0 還是 NULL,因此解除參照 Null 指標,並導致分段錯誤。


if (ptr == '\0') {
*ptr = val;
...
}
範例 4:在以下程式碼中,程式設計師明確地將變數 ptr 設定為 NULL。之後,程式設計師先解除參照 ptr,再檢查物件是否為 null 值。


*ptr = NULL;
...
ptr->field = val;
...
}
desc.controlflow.cpp.null_dereference
Abstract
程式可能會解除參照 Null 指標,因此造成 NullPointerException
Explanation
Null 指標錯誤通常是由於一個或者多個程式設計人員的假設被破解而造成的。

大部分的 Null 指標問題都會導致一般軟體可靠性問題,但是如果攻擊者蓄意觸發 Null 指標解除參照的話,攻擊者就可能會使用引發的異常來略過安全性邏輯,或是使應用程式洩漏出除錯資訊,這些資訊對於計畫後續攻擊很有價值。

範例:在以下程式碼中,程式設計人員假設系統永遠會定義一個名為「cmd」的屬性。如果攻擊者可以控制程式環境,使「cmd」變成未定義狀態,那麼程式會在嘗試呼叫 trim() 方法時拋出一個 Null 指標異常。


String val = null;
...
cmd = System.getProperty("cmd");
if (cmd)
val = util.translateCommand(cmd);
...
cmd = val.trim();
desc.controlflow.java.null_dereference