C代码审计之整数溢出漏洞
整数溢出就是对整数操作时产生了超过表示范围的数值
无符号整数不会发生溢出。如果超出表示范围,无符号整数进行回绕,CF寄存器(假装是结果的最高位)会记录下进位/借位操作。
//假设四位无符号整数进行运算 1111 + 1111 = 11110 0000 - 1111 = 10001
回绕:整数表示范围的上界与下界形成闭环,上界+1=下界,下界-1=上界
溢出:有符号整数超出表示范围就会产生溢出,编译器的一般做法也是回绕,此时OF寄存器值为1
截断:将一个较大宽度的数存入一个宽度小的操作数中,高位发生截断
无符号整数表示
有符号整数表示
造成整数溢出的情况:
1、未限制范围
2、错误的类型转换
错误的类型转换
void init(int size){
if (size < MAX_ARRAY_SIZE){
array = malloc(size);
}
}
//malloc里所需的参数类型是size_t(无符号整数),而传入的却是int类型。假设size为负数,那么经过类型转换(int转为unsigned int)并且回绕后,size将变成一个巨大的数。
修复方案:把int size改成size_t size
截断错误
int main(int argc, char *argv[]) {
unsigned short int total;
total = strlen(argv[1]) + strlen(argv[[2]) + 1;
char *buff = (char * )malloc(total);
strcpy(buff, argv[1]);
strcat(buff, argv[2]);
}
//乍一看,动态分配了缓冲区大小,很安全
//仔细看total赋值的语句,将size_t(unsigned int)类型赋值给unsigned short int类型,属于较大宽度的数存入一个宽度小的数,只要strlen(argv[1]) + strlen(argv[[2])大于unsigned short int所能取到的最大值,经过高位截断后,缓冲区大小必然比实际的小
//实际输入比缓冲区大,造成了缓冲区溢出漏洞
修复方案:
plan A. 限制输入字符的个数
plan B. total定义为更大宽度的数据类型
整数逻辑错误
int *table = NULL;
int insert_in_table(int pos, int value){ //在table数组pos位置插入value
if(!table){
table = (int *)malloc(sizeof(int) * 100)
}
if(pos > 99){
return -1;
}
table[pos] = value;
return 0;
}
//pos是int类型,且程序没有对数组的下界做限制
//假设pos为负数,table[pos] = value会将value写入内存中table数组之前的位置,造成内存的任意写漏洞
修复方案:
plan A. 同时检查上界和下界
plan B. 将pos声明成无符号整数
总结
严格选择整数类型。
整数有明确的范围定义,可以阻止可能引起整数溢出的非常大或非常小的数据进入系统。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步