程式碼品質不佳,會導致無法預料的行為。從使用者的角度來看,這通常表現為可用性不佳。對於攻擊者而言,這提供了以意想不到的方式向系統施加壓力的機會。
free()
兩次會導致 Buffer overflow。free()
做為一個引數來呼叫,就會出現 double free (釋放相同的記憶體空間兩次) 錯誤。free()
兩次,會導致 Buffer overflow。當程式使用相同引數呼叫 free()
兩次,就會毀損程式中的記憶體管理資料結構。這樣的毀損會使程式當機,或者在某些情況下,還會導致之後兩次的 malloc()
呼叫回傳相同的指標。如果 malloc()
兩次回傳值都相同,且程式之後讓攻擊者控制整個已經寫入雙倍分配記憶體的資料,此程式就變得容易受到 Buffer overflow 攻擊。
char* ptr = (char*)malloc (SIZE);
...
if (abrt) {
free(ptr);
}
...
free(ptr);
#include <stdio.h>
int main() {
/* Nothing to see here; newline RLI /*/ return 0 ;
printf("Do we get here?\n");
return 0;
}
Example 1
中,從右到左隔離 (RLI) Unicode 雙向控制字元導致程式碼被視為以下內容:
#include <stdio.h>
int main() {
/* Nothing to see here; newline; return 0 /*/
printf("Do we get here?\n");
return 0;
}
strncpy()
的範圍函數,使用不正確時也會引起弱點。大多數 Buffer overflow 弱點的根本原因,都是緩衝區的處理,加上對資料的大小或組成假設錯誤。
void wrongNumberArgs(char *s, float f, int d) {
char buf[1024];
sprintf(buf, "Wrong number of %.512s");
}
strncpy()
的範圍函數,使用不正確時也會引起弱點。大多數 Buffer overflow 弱點的根本原因,都是緩衝區的處理,加上對資料的大小或組成假設錯誤。%d
格式規範從浮點數轉換 f
。
void ArgTypeMismatch(float f, int d, char *s, wchar *ws) {
char buf[1024];
sprintf(buf, "Wrong type of %d", f);
...
}
Intent
。隱含的內部 Intent 可能會使系統遭受對內部元件的 man-in-the-middle 樣式攻擊。Intent
使用內部元件定義的自訂動作。隱含 Intent 可以促進從任何指定外部元件呼叫 Intent,而無需了解特定元件。將兩者相結合,會允許應用程式從所需的應用程式內容外部存取指定給特定內部使用的 Intent。Intent
的能力,可以引發從資訊洩漏、Denial of Service 到遠端程式碼執行等各種不同嚴重程度的 man-in-the-middle 攻擊,具體取決於 Intent
指定之內部動作的能力。Intent
。
...
val imp_internal_intent_action = Intent("INTERNAL_ACTION_HERE")
startActivity(imp_internal_intent_action)
...
PendingIntent
。隱含 Pending Intent 可能會導致安全性弱點,例如 Denial of Service、私人和系統資訊洩漏以及提升特權。Intent
。隱含 Intent 有助於從任何特定外部元件呼叫 Intent,並使用通用名稱和篩選器來確定執行。Intent
做為 PendingIntent
建立時,可能會導致 Intent
被傳送到在預期暫存內容外部執行的非預期元件,從而使系統容易受到諸如 Denial of Service、私人和系統資訊洩漏和提升特權等的攻擊。PendingIntent
。
...
val imp_intent = Intent()
val flag_mut = PendingIntent.FLAG_MUTABLE
val pi_flagmutable_impintintent = PendingIntent.getService(
this,
0,
imp_intent,
flag_mut
)
...
PendingIntent
的旗標值設為 FLAG_MUTABLE
。建立的 Pending Intent 具有 FLAG_MUTABLE
旗標值時,很容易受到下游設定的未指定 Intent
欄位的影響,這可能會修改 Intent
的能力並使系統容易受到攻擊。PendingIntent
後修改其底層 Intent
,可能會使系統容易受到攻擊。這主要取決於底層 Intent
的整體能力。在大多數情況下,最佳方式是將 PendingIntent
旗標設為 FLAG_IMMUTABLE
來防止潛在問題。FLAG_MUTABLE
旗標值建立 PendingIntent
。
...
val intent_flag_mut = Intent(Intent.ACTION_GTALK_SERVICE_DISCONNECTED, Uri.EMPTY, this, DownloadService::class.java)
val flag_mut = PendingIntent.FLAG_MUTABLE
val pi_flagmutable = PendingIntent.getService(
this,
0,
intent_flag_mut,
flag_mut
)
...
read()
時未能回傳預期的位元組數:
char* getBlock(int fd) {
char* buf = (char*) malloc(BLOCK_SIZE);
if (!buf) {
return NULL;
}
if (read(fd, buf, BLOCK_SIZE) != BLOCK_SIZE) {
return NULL;
}
return buf;
}
CALL "CBL_ALLOC_MEM"
USING mem-pointer
BY VALUE mem-size
BY VALUE flags
RETURNING status-code
END-CALL
IF status-code NOT = 0
DISPLAY "Error!"
GOBACK
ELSE
SET ADDRESS OF mem TO mem-pointer
END-IF
PERFORM write-data
IF ws-status-code NOT = 0
DISPLAY "Error!"
GOBACK
ELSE
DISPLAY "Success!"
END-IF
CALL "CBL_FREE_MEM"
USING BY VALUE mem-pointer
RETURNING status-code
END-CALL
GOBACK
.
dealloc()
方法中釋放記憶體。init()
方法中分配了記憶體,但無法在 deallocate()
方法中將其釋放,導致記憶體洩露:
- (void)init
{
myVar = [NSString alloc] init];
...
}
- (void)dealloc
{
[otherVar release];
}
realloc()
調整原始分配大小失敗時,洩露了分配記憶體區塊。
char* getBlocks(int fd) {
int amt;
int request = BLOCK_SIZE;
char* buf = (char*) malloc(BLOCK_SIZE + 1);
if (!buf) {
goto ERR;
}
amt = read(fd, buf, request);
while ((amt % BLOCK_SIZE) != 0) {
if (amt < request) {
goto ERR;
}
request = request + BLOCK_SIZE;
buf = realloc(buf, request);
if (!buf) {
goto ERR;
}
amt = read(fd, buf, request);
}
return buf;
ERR:
if (buf) {
free(buf);
}
return NULL;
}
realloc()
的呼叫未能調整原始配置的大小,則以下 Micro Focus COBOL 程式就會洩漏配置的記憶體區塊。
CALL "malloc" USING
BY VALUE mem-size
RETURNING mem-pointer
END-CALL
ADD 1000 TO mem-size
CALL "realloc" USING
BY VALUE mem-pointer
BY VALUE mem-size
RETURNING mem-pointer
END-CALL
IF mem-pointer <> null
CALL "free" USING
BY VALUE mem-pointer
END-CALL
END-IF
NullException
。cmd
」的屬性。如果攻擊者可以控制程式環境,使「cmd
」變成未定義狀態,那麼程式會在嘗試呼叫 Trim()
方法時拋出一個 Null 指標異常。
string cmd = null;
...
cmd = Environment.GetEnvironmentVariable("cmd");
cmd = cmd.Trim();
null
之前先解除參照可能為 null
的指標,將會造成「解除參照之後檢查」的錯誤。當程式執行明確的 null
檢查,但仍繼續解除參照已知為 null
的指標時,將會造成「檢查後解除參照」的錯誤。這種類型的錯誤通常是打字錯誤或程式設計師的疏忽所造成。當程式明確的將某指標設定為 null
,卻在之後解除參考該指標,則會發生儲存後解除參照錯誤。這種錯誤通常是由於程式設計師在宣告變數時將變數初始化為 null
所致。ptr
不是 NULL
。當程式設計師取消參照指標時,這個假設就變得清楚。當程式設計師檢查 ptr
為 NULL
時,這個假設其實就出現其矛盾之處。若在 if
指令中檢查 ptr
時,其可為 NULL
,則解除參照時也可為 NULL
,並產生分段錯誤。範例 2:在以下程式碼中,程式設計師確定變數
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
是 NULL
,並在之後以錯誤的方式解除參照。若在 if
陳述式中檢查 ptr
時,其非 NULL
,就會發生 null
解除參照,從而導致分段錯誤。範例 3:在以下程式碼中,程式設計師忘記了字串
if (ptr == null) {
ptr->field = val;
...
}
'\0'
實際上是 0 還是 NULL
,因此解除參照 Null 指標,並導致分段錯誤。範例 4:在以下程式碼中,程式設計師明確地將變數
if (ptr == '\0') {
*ptr = val;
...
}
ptr
設定為 NULL
。之後,程式設計師先解除參照 ptr
,再檢查物件是否為 null
值。
*ptr = NULL;
...
ptr->field = val;
...
}
NullPointerException
。cmd
」的屬性。如果攻擊者可以控制程式環境,使「cmd
」變成未定義狀態,那麼程式會在嘗試呼叫 trim()
方法時拋出一個 Null 指標異常。
String val = null;
...
cmd = System.getProperty("cmd");
if (cmd)
val = util.translateCommand(cmd);
...
cmd = val.trim();
SqlClientPermission
物件,其規定使用者可連接到資料庫的方式。在此範例中,程式把 false
作為第二個參數傳遞給構造函數,控制使用者是否可使用空白密碼進行連接。若傳送的參數值為 false,表示不允許密碼為空白。
...
SCP = new SqlClientPermission(pstate, false);
...
PermissionState
物件代替了所有傳遞至第二個參數的值,因此構造函數允許使用空白密碼進行資料庫連線,這與第二個引數互相矛盾。若要禁止使用空白密碼,程式應該把 PermissionState.None
傳遞給建構函數的第一個參數。因為其功能的不明確,SqlClientPermission
構造函數的雙參數版本已遭反對,改用單參數版本,單參數版本可提供與雙參數版本相同的功能,但是避免了誤譯的風險。getpw()
來驗證純文字密碼是否與使用者加密密碼相符。如果密碼有效,則函數將把 result
設為 1;如果無效,則將其設為 0。
...
getpw(uid, pwdline);
for (i=0; i<3; i++){
cryptpw=strtok(pwdline, ":");
pwdline=0;
}
result = strcmp(crypt(plainpw,cryptpw), cryptpw) == 0;
...
getpw(
) 函數會產生問題,因為這會導致傳遞至其第二個參數的緩衝區發生溢位。鑒於存在這一弱點,getpw()
已由 getpwuid()
取代,後者會執行與 getpw()
相同的查詢,但是會傳回指向靜態分配之結構的指標以降低風險。
...
String name = new String(nameBytes, highByte);
...
nameBytes
所呈現的字串而定。由於用於編碼字串的字元組的演變,所以不推薦使用此建構函式,取而代之的是新的構造函式。新的構造函式可接受作為名為 charset
的其中一個參數,用來編碼字元組以進行字元轉換。Digest::HMAC
stdlib,但由於在發行中意外涉及,因此在文件中明確不鼓勵使用。
require 'digest/hmac'
hmac = Digest::HMAC.new("foo", Digest::RMD160)
...
hmac.update(buf)
...
Digest::HMAC
類別時便會立即捨棄。由於實驗性和未正確測試的程式碼造成此要求無法如預期般運作,強烈勸阻使用此類別,尤其考慮到加密式功能涉及的關係 HMAC。IsBadXXXPtr()
類別的原因很多。這些函數的特性如下:IsBadWritePtr()
以嘗試防止不良的記憶體寫入。
if (IsBadWritePtr(ptr, length))
{
[handle error]
}
public class Totaller {
private int total;
public int total() {
...
}
}
synchronized(this) { }
int un$afe;
r
指定值,然後在沒有使用的情況下將其覆寫。
int r = getNum();
r = getNewNum(buf);
r
指定值,然後在沒有使用的情況下將其覆寫。
int r = getNum();
r = getNewNum(buf);
r
指定值,然後在沒有使用的情況下將其覆寫。
r = getName();
r = getNewBuffer(buf);
r
指定值,然後在沒有使用的情況下將其覆寫。
r = getName();
r = getNewBuffer(buf);
i
) 被使用了兩次。變數 j
從未使用過。
int i,j;
for (i=0; i < outer; i++) {
for (i=0; i < inner; i++) {
...