輸入驗證和表示法問題是由中繼字元、替代編碼和數值表示法引起的。信任輸入會導致安全問題。問題包括:「Buffer Overflows」、「Cross-Site Scripting」攻擊、「SQL Injection」及其他許多問題。
send
函數及其變體允許程式設計師修改針對函數的 Ruby 存取規範。特別是,程式設計師可藉此存取通常不允許的私人和受保護的欄位、函數和行為。paramName
URL 參數的任何轉換或驗證。
...
<bookmark>
<method>#{paramHandler.handleParams}</method>
<url-parameter>
<name>paramName</name>
<value>#{requestScope.paramName}</value>
</url-parameter>
</bookmark>
...
userClassPath
來決定搜尋要載入的類別所在的目錄。
...
productCategory = this.getIntent().getExtras().getString("userClassPath");
DexClassLoader dexClassLoader = new DexClassLoader(productCategory, optimizedDexOutputPath.getAbsolutePath(), null, getClassLoader());
...
userClassPath
的結果來指向所控制的其他路徑,從而讓攻擊者利用應用程式的提升權限,載入程式庫並潛在地執行任意程式碼。因為程式不會驗證從環境讀取的值,所以如果攻擊者可以控制 userClassPath
的值,則攻擊者便可使用與原始應用程式相同的權限,愚弄應用程式,讓應用程式指向他們所控制的目錄,從而載入他們所定義的類別。userOutput
來決定應寫入最佳化 DEX 檔案的目錄。
...
productCategory = this.getIntent().getExtras().getString("userOutput");
DexClassLoader dexClassLoader = new DexClassLoader(sanitizedPath, productCategory, null, getClassLoader());
...
userOutput
值變更為他們所控制的目錄,如外部儲存裝置。一旦完成竄改,便只需將輸出的 ODEX 檔案替換為惡意 ODEX 檔案,就可以使用與原始應用程式相同的權限執行該動作。ModelState.IsValid
檢查模型是否通過驗證。class.classLoader
的特別 bean 屬性,這些屬性允許攻擊者取代系統屬性,並可能執行任意程式碼。
String prop = request.getParameter('prop');
String value = request.getParameter('value');
HashMap properties = new HashMap();
properties.put(prop, value);
BeanUtils.populate(user, properties);
strncpy()
的範圍函數,使用不正確時也會引起弱點。大多數 Buffer overflow 弱點的根本原因,都是緩衝區的處理,加上對資料的大小或組成假設錯誤。gets()
函數,將一個任意長度的資料讀取到堆疊緩衝區。因為沒有什麼方法可以限制這個函數讀取的資料量,所以使用者輸入的字元數必須少於 BUFSIZE
,以確保程式碼的安全性。範例 1.b:此範例顯示只要使用
...
char buf[BUFSIZE];
gets(buf);
...
>>
運算子將輸入讀取到 char[]
字串中,即可輕易模仿 C++ 中 gets()
函數不安全的運作方式。範例 2:雖然這個範例中的程式碼也是依賴於使用者的輸入來控制它的運作方式,但是它會藉由使用邊界記憶體複製函數
...
char buf[BUFSIZE];
cin >> (buf);
...
memcpy()
增加一個間接的層面。此函數接受目的緩衝區、來源緩衝區,以及要複製的位元組數量。輸入緩衝區由 read()
的範圍呼叫所填滿,但使用者指定 memcpy()
要複製的位元組數量。
...
char buf[64], in[MAX_SIZE];
printf("Enter buffer contents:\n");
read(0, in, MAX_SIZE-1);
printf("Bytes to copy:\n");
scanf("%d", &bytes);
memcpy(buf, in, bytes);
...
lccopy()
的函數將一個字串做為引數讀取,然後將這個字串中所有的大寫字母轉化成小寫字母回傳一個堆疊分配的字串副本。這個函數不會對其輸入執行範圍檢查,因為程式預期 str
始終小於 BUFSIZE
。如果攻擊者避開對呼叫 lccopy()
的程式碼的測試,或者,如果程式碼有什麼變化,使得關於 str
長度的假設失真,那麼 lccopy()
就會在 strcpy()
超出邊界的呼叫過程中溢位 buf
。範例 4:下列程式碼示範了第三種情況,其中程式碼太過複雜以致無法輕易預測其行為。這段程式碼來自於主流的 libPNG 圖像解碼器,此解碼器廣泛用於多種應用程式。
char *lccopy(const char *str) {
char buf[BUFSIZE];
char *p;
strcpy(buf, str);
for (p = buf; *p; p++) {
if (isupper(*p)) {
*p = tolower(*p);
}
}
return strdup(buf);
}
png_crc_read()
複製的資料量。不過,在測試長度之前,程式碼會立即對 png_ptr->mode
執行檢查。檢查失敗時,系統會發出警告,而處理會繼續執行下去。由於 length
會在一個 else if
區塊中進行測試,所以當第一個檢查失敗時,就不會測試 length
;且在呼叫 png_crc_read()
期間對其的盲目使用易引發堆疊 Buffer overflow。範例 5:此範例同樣證明了第三種情況,程式的複雜性將 Buffer overflow 的問題暴露出來。在此案例中,弱點歸咎於函數某個不明確的介面,而不是程式碼的結構 (就如同前面一個範例中所描述的)。
if (!(png_ptr->mode & PNG_HAVE_PLTE)) {
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Missing PLTE before tRNS");
}
else if (length > (png_uint_32)png_ptr->num_palette) {
png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_finish(png_ptr, length);
return;
}
...
png_crc_read(png_ptr, readbuf, (png_size_t)length);
getUserInfo()
函數採用一個定義為多位元組字元串的使用者名和一個指標來組成使用者資訊的結構,並將使用者資訊填入這個結構。因為 Windows 對使用者名稱的 authentication 是使用統一的字元編碼標準,所以 username
是第一個從多位元組字元串轉換成統一字元編碼標準的字串的參數。函數接著會不正確地以位元組而非字元傳送 unicodeUser
的大小。呼叫 MultiByteToWideChar()
可能會因此而將最多 (UNLEN+1)*sizeof(WCHAR)
個寬字元,或(UNLEN+1)*sizeof(WCHAR)*sizeof(WCHAR)
個位元組寫入 unicodeUser
陣列,而僅為該陣列分配了 (UNLEN+1)*sizeof(WCHAR)
個位元組。如果 username
字串包含了多於 UNLEN
的字元,那麼呼叫 MultiByteToWideChar()
將會溢出 unicodeUser
緩衝區。
void getUserInfo(char *username, struct _USER_INFO_2 info){
WCHAR unicodeUser[UNLEN+1];
MultiByteToWideChar(CP_ACP, 0, username, -1,
unicodeUser, sizeof(unicodeUser));
NetUserGetInfo(NULL, unicodeUser, 2, (LPBYTE *)&info);
}
strncpy()
的範圍函數,使用不正確時也會引起弱點。大多數 Buffer overflow 弱點的根本原因,都是緩衝區的處理,加上對資料的大小或組成假設錯誤。c
,因為 double
類型需要為 c
所分配的空間還要大的空間。
void formatString(double d) {
char c;
scanf("%d", &c)
}