常见的安全编码问题:
安全输入
1输入验证方法
强输入验证
白名单
黑名单
间接选择
避免黑名单
不要混淆可用性和安全性
拒绝不良数据
默认执行正确的输入验证
检查输入长度
限制数值输入
2输入验证原则
接受输入,但是不能全部信任
对所有的输入必须进行验证
不要修复恶意的输入
3输入验证内容
所有的输入
各种来源的输入
- 命令行参数
- sql注入
建立信任边界
将可信数据和不可信数据分开存储
危害
缓冲区溢出
SQL注入
字符串问题
无边界检查(unbounded string operation)
c/c++没有边界检查
gets()函数
没有提供方法对输入的字符个数进行限制,会导致缓冲区溢出的问题使用fgets()和gets_s()进行替换
差一错误(off-by-one-error)
一字节溢出
在比较时使用了<,没有考虑到一个序列是从0开始,而不是从1开始,忽略了字符串最后的结束标志'\0'
strncpy(char* dst,const char* src,size_t n);
常见错误:
将数据写到目标缓冲区外
边界通过源数据的大小确定,没有考虑目标地址是否会溢出
使用的目标缓冲区没有正确的终止
没有在缓冲区中写入终止符
strncpy调用重复写入了NULL终止符
strncat(char* dst,char* src,size_t bound)
边界参数应该是目标缓冲区剩余容量的大小
目标缓冲区需要包含NULL终止符
确保源和目的缓冲区都包含NULL终止符
空结尾错误(Null end error)
字符串截断(string truncation)
如果源数据的长度大于边界参数的值,则有界函数即使调用正确,依然会发生数据截断错误
避免截断错误
- 动态内存分配
- 静态内存分配面临的2类数据截断错误
- 字符串由于目标缓冲区大小的限制导致截断,使得字符串语义被迫截断
- 无正确终止符的字符串
- 避免悄无生息的截断
安全的内存管理
1.缓冲区溢出
数据写到所分配内存之外的地方
缓冲区溢出漏洞用来覆盖内存中的值,从而达到攻击者的目的
缓冲区溢出错误给攻击者大量机会控制有漏洞的代码
程序内存分配
栈区:类似数据结构中的栈 编译器自动释放
堆区:类似于链表 OS释放
全局区:全局变量和静态变量 OS释放
文字常量区:存放字符串常量 OS释放
程序代码区:存放函数体的二进制代码