Linux C/C++开发常见错误及其漏洞(一)

一、通用规范

1、代码简洁精炼,美观,可读性好,高效率,高复用,可移植性好,高内聚,低耦合,没有冗余, 不符合这些原则,必须特别说明。

2、规范性,代码有规可循。特殊排版、特殊语法、特殊指令,必须特别说明。

二、常见的错误

1、复制、粘贴

Linux C/C++开发常见错误及其漏洞(一)_第1张图片

Linux C/C++开发常见错误及其漏洞(一)_第2张图片

Linux C/C++开发常见错误及其漏洞(一)_第3张图片

Linux C/C++开发常见错误及其漏洞(一)_第4张图片

当错误产生时会发生什么结果?
错误的数据/返回数据、条件丢失、难以调试、肉眼难辨

2、 ?:

Linux C/C++开发常见错误及其漏洞(一)_第5张图片

Linux C/C++开发常见错误及其漏洞(一)_第6张图片

?:优先级小于前置的 | 、+等运算符,使语义发生变化
此类运算符与其他运算符结合使用时请使用()。

3、无意义的指针与0比较

Linux C/C++开发常见错误及其漏洞(一)_第7张图片

Linux C/C++开发常见错误及其漏洞(一)_第8张图片

有效指针不会小于0!,大部分情况下应该是指针代表的某个数据与0比较,否则将会失去比较的意义。

4、return后“;”丢失

Linux C/C++开发常见错误及其漏洞(一)_第9张图片

Linux C/C++开发常见错误及其漏洞(一)_第10张图片

上述例子并不会出现编译或运行错误,但真实逻辑行为已经改变!
编码中应该注意那不引人注意的“;”。

5、循环中alloc或new等内存

Linux C/C++开发常见错误及其漏洞(一)_第11张图片

Linux C/C++开发常见错误及其漏洞(一)_第12张图片

显示的使用内存分配函数但是没有明确的内存释放调用
宏形式内存分配,其他人使用时可能并不清楚是否需要释放
使用时除特殊情况下应该避免循环中连续内存分配,即使需要也应该检查内存是否够用!
确实存在的场景应该有内存使用警告,防止OOM。

考虑如何使用内存? 内存池(使用量以及空闲量)

6、局部指针储存于外部变量

Linux C/C++开发常见错误及其漏洞(一)_第13张图片

Linux C/C++开发常见错误及其漏洞(一)_第14张图片

在函数内部使用时可能并不会出现错误,但是对于外部指针已经有确切的值存在,可能会影响后期
对于该外部指针的使用,设想如果后续会根据此外部指针是否有正确的数据进行判断将可能发生某些
超出预期的行为。(看起来是另类的野指针)

7、sizeof(1)

Linux C/C++开发常见错误及其漏洞(一)_第15张图片

Linux C/C++开发常见错误及其漏洞(一)_第16张图片

Linux C/C++开发常见错误及其漏洞(一)_第17张图片

上述SRC、PID以及PPS仅仅是一个指针,在32或64位系统上返回4或8。
在初始应该为0的某些位置如果使用了上述错误的方式,可能导致数据判断错误,从而进入错误的逻辑。

应该使用SIZEOF(LETTER) * 30
还有类似的 SNPRINTF

8、sizeof (2)

Linux C/C++开发常见错误及其漏洞(一)_第18张图片

const char * header为传入参数

此类为SIZEOF(PTR) / SIZEOF(TYPE),判断或所得数据会失准。
PTR应该是实际数据长度。

左侧ELSE分支将不会执行,也就是某些情况下HEADER可能不会有结束符存在;
设想如果后续有对HEADER的STRCPY等类似操作会发生什么?

WHILE(HEADER[I] != '\0') {} ???

9、“;”位置错误

Linux C/C++开发常见错误及其漏洞(一)_第19张图片

Linux C/C++开发常见错误及其漏洞(一)_第20张图片

10、vector:empty/clear

Linux C/C++开发常见错误及其漏洞(一)_第21张图片

好评论。可惜,代码做了完全不同的事情。这应该是在这里写的:THIS-> FSPECS.CLEAR();

同时应该注意是否要回缩向量空间。SWAP()。

某一类的库可能存在相似的命令,它可能会产生歧义,尤其是第三方库,需要确切知道差异,防止误用。

11、数组越界

Linux C/C++开发常见错误及其漏洞(一)_第22张图片

Linux C/C++开发常见错误及其漏洞(一)_第23张图片

Linux C/C++开发常见错误及其漏洞(一)_第24张图片

越界赋值行为可能不会产生错误,但可能导致结果无法预测。

12、if…else嵌套行为

Linux C/C++开发常见错误及其漏洞(一)_第25张图片

Linux C/C++开发常见错误及其漏洞(一)_第26张图片

Linux C/C++开发常见错误及其漏洞(一)_第27张图片

嵌套时尽量使用{ }并格式对齐,同时注意宏定义情况下不同逻辑分支执行情况。

13、变量未初始化

Linux C/C++开发常见错误及其漏洞(一)_第28张图片

Linux C/C++开发常见错误及其漏洞(一)_第29张图片

Linux C/C++开发常见错误及其漏洞(一)_第30张图片

Linux C/C++开发常见错误及其漏洞(一)_第31张图片

例外:对于全局变量以及没有初值的静态变量则无需初始化!因为在程序加载时会被清空。

14、高危函数

Linux C/C++开发常见错误及其漏洞(一)_第32张图片

打印类函数如PRINTF, FPRINTF, SPRINTF以及SNPRINTF等均存在一个字符串格式化攻击问题,即参数为%S、%P、%N等。
其他的如FGETS,STRCPY等一系列不检查输入长度的函数。
文件读取类函数直接赋值给某数组导致越界等。

Linux C/C++开发常见错误及其漏洞(一)_第33张图片

Linux C/C++开发常见错误及其漏洞(一)_第34张图片

尤其注意%N,它会改变变量的值,%N会将其之前数据的偏移量赋值给下一个变量。

15、结构体定义丢失“;”

Linux C/C++开发常见错误及其漏洞(一)_第35张图片

可以看出结构体丢失;号并不一定会出现错误。
如果后接函数定义会认为函数返回值为结构体类型。

16、资源释放问题

Linux C/C++开发常见错误及其漏洞(一)_第36张图片

系统句柄类资源未释放。
open类函数打开文件,但是由于某些异常的return导致句柄未正确关闭。

Linux C/C++开发常见错误及其漏洞(一)_第37张图片

malloc、new内存没有正确释放

17、程序入口参数检查

Linux C/C++开发常见错误及其漏洞(一)_第38张图片

类似于printf类型的打印函数族,在精心构造的情况下可以被利用

Linux C/C++开发常见错误及其漏洞(一)_第39张图片

Linux C/C++开发常见错误及其漏洞(一)_第40张图片

如上:创建ccc.txt并删除了所有core.*

18、漏洞利用

缓冲区溢出的攻击大致分为以下几类:
栈溢出(stack smashing):未检查输入缓冲区长度,导致数组越界,覆盖栈中局部变量空间之上的栈桢指针%ebp以及函数返回地址retaddr。
堆溢出(malloc/free heapcorruption):一种是和传统的栈溢出一样, 当输入超出malloc()预先分配的空间大小,就会覆盖掉这段空间之后的一段存储区域,如果该存储区域有一个重要的变量被改写?
格式化字符窜漏洞(format stringvulnerability):如果格式串可由用户定制,攻击者就可以任意伪造格式串,利用*printf()系列函数的特性就可以窥探堆栈空间的内容,超长输入可以引发传统的缓冲区溢出,或是用”%n”覆盖指针、返回地址等。
整形变量溢出(integer variableoverflow):利用整数的范围、符号等问题触发安全漏洞,大多数整形溢出不能直接利用,但如果该整形变量决定内存分配等操作,我们就有可能间接利用该漏洞。
其他的攻击手法(others):利用ELF文件格式的特性如:覆盖.plt(过程连接表)、.dtor(析构函数指针)、.got(全局偏移表)、return-to-libc(返回库函数)等的方式进行攻击。
Stackguard:因为缓冲区溢出的通常都会改写函数返回地址,stackguard是个编译器补丁,它产生一个"canary"值(一个单字)放到返回地址的前面,如果 当函数返回时,发现这个canary的值被改变了,就证明可能有人正在试图进行缓冲区溢出攻击,程序会立刻响应,发送一条入侵警告消息给syslogd, 然后终止进程。

今天就先到这里吧,第二篇将讲述如何利用这些漏洞达到权限提升或破解的目的......

你可能感兴趣的:(技术摘要,安全漏洞,底层应用开发,linux,代码规范)