在計算時需要考慮整數(shù)溢出的可能,尤其在進行內(nèi)存操作時,需要對分配、拷貝等大小進行合法校驗,防止整數(shù)溢出導(dǎo)致的漏洞。
錯誤(該例子在計算時產(chǎn)生整數(shù)溢出)
const kMicLen = 4;
// 整數(shù)溢出
void Foo() {
int len = 1;
char payload[10] = { 0 };
char dst[10] = { 0 };
// Bad, 由于len小于4字節(jié),導(dǎo)致計算拷貝長度時,整數(shù)溢出
// len - MIC_LEN == 0xfffffffd
memcpy(dst, payload, len - kMicLen);
}
正確例子
void Foo() {
int len = 1;
char payload[10] = { 0 };
char dst[10] = { 0 };
int size = len - kMicLen;
// 拷貝前對長度進行判斷
if (size > 0 && size < 10) {
memcpy(dst, payload, size);
printf("memcpy good\n");
}
}
關(guān)聯(lián)漏洞:
高風(fēng)險-內(nèi)存破壞
在進行計算或者操作時,如果使用的最大值或最小值不正確,使得該值比正確值多1或少1,可能導(dǎo)致安全風(fēng)險。
錯誤:
char firstname[20];
char lastname[20];
char fullname[40];
fullname[0] = '\0';
strncat(fullname, firstname, 20);
// 第二次調(diào)用strncat()可能會追加另外20個字符。如果這20個字符沒有終止空字符,則存在安全問題
strncat(fullname, lastname, 20);
正確:
char firstname[20];
char lastname[20];
char fullname[40];
fullname[0] = '\0';
// 當使用像strncat()函數(shù)時,必須在緩沖區(qū)的末尾為終止空字符留下一個空字節(jié),避免off-by-one
strncat(fullname, firstname, sizeof(fullname) - strlen(fullname) - 1);
strncat(fullname, lastname, sizeof(fullname) - strlen(fullname) - 1);
對于 C++ 代碼,再次強烈建議使用 string
、vector
等組件代替原始指針和數(shù)組操作。
關(guān)聯(lián)漏洞:
高風(fēng)險-內(nèi)存破壞
在一些涉及大小端數(shù)據(jù)處理的場景,需要進行大小端判斷,例如從大段設(shè)備取出的值,要以大段進行處理,避免端序錯誤使用。
關(guān)聯(lián)漏洞:
中風(fēng)險-邏輯漏洞
在進行除法運算時,需要判斷被除數(shù)是否為零,以防導(dǎo)致程序不符合預(yù)期或者崩潰。
錯誤:
double divide(double x, double y) {
return x / y;
}
int divide(int x, int y) {
return x / y;
}
正確:
double divide(double x, double y) {
if (y == 0) {
throw DivideByZero;
}
return x / y;
}
關(guān)聯(lián)漏洞:
低風(fēng)險-拒絕服務(wù)
在有符號和無符號數(shù)字參與的運算中,需要注意類型強轉(zhuǎn)可能導(dǎo)致的邏輯錯誤,建議指定參與計算時數(shù)字的類型或者統(tǒng)一類型參與計算。
錯誤例子
int Foo() {
int len = 1;
unsigned int size = 9;
// 1 < 9 - 10 ? 由于運算中無符號和有符號混用,導(dǎo)致計算結(jié)果以無符號計算
if (len < size - 10) {
printf("Bad\n");
} else {
printf("Good\n");
}
}
正確例子
void Foo() {
// 統(tǒng)一兩者計算類型為有符號
int len = 1;
int size = 9;
if (len < size - 10) {
printf("Bad\n");
} else {
printf("Good\n");
}
}
關(guān)聯(lián)漏洞:
高風(fēng)險-內(nèi)存破壞
中風(fēng)險-邏輯漏洞
在進行數(shù)據(jù)大小比較時,要合理地校驗數(shù)據(jù)的區(qū)間范圍,建議根據(jù)數(shù)字類型,對其進行最大和最小值的判斷,以防止非預(yù)期錯誤。
錯誤:
void Foo(int index) {
int a[30] = {0};
// 此處index是int型,只考慮了index小于數(shù)組大小,但是并未判斷是否大于0
if (index < 30) {
// 如果index為負數(shù),則越界
a[index] = 1;
}
}
正確:
void Foo(int index) {
int a[30] = {0};
// 判斷index的最大最小值
if (index >=0 && index < 30) {
a[index] = 1;
}
}
關(guān)聯(lián)漏洞:
高風(fēng)險-內(nèi)存破壞
更多建議: