缓冲区溢出指的是应用程序将数据写到一个较小缓冲区中所导致的程序漏洞。缓冲区溢出漏洞通常被攻击者用于重写内存中的数据。由于象C和C++语言,程序员可对内存进行操纵就会导致缓冲区溢出风险。
在C和C++程序中发现的很多早期缓冲区溢出漏洞,都是由字符串操作引起的。比如使用strcpy()和strcat()这样的函数。针对这种情况,引入了这些函数的有边界限制的等价函数,如strncpy()和strncat()。这些有界函数接收一个参数,限制写入到目标缓冲区中的数据总量。
在使用不安全的编程语言时对字符串进行操作时要时刻小心。要当心用户的输入,限制长度和边界,采用一些安全的字符串类库将使应用程序更加安全。
防止缓冲区溢出攻击的最佳方式是使用强制执行内存安全和类型安全的编程语言,例如Java语言和C#语言。安全语言应该具备确保程序内存分配范围的两种特性:内存安全和类型安全。内存安全是指程序不读入或者不写出超过所分配区域的数据。为了保证内存安全,编程语言必须强制类型安全,以记住内存分配边界。
Java不要求程序员显示地分配内存和释放内存,都是由垃圾收集器自动执行的。垃圾收集器会不时检查个对象的各个引用,并回收无引用对象所占有的内存。判断一块内存空间是否符合回收标准有两个:
1)给对象赋予了空值null,以后再也没有调用过。
2)给对象赋予了新值,重新分配了内存空间。
在Java程序中也会出现内存泄漏的情况,即这些对象是可达的(会被引用),同时这些对象是无用的(程序以后不会再使用这些对象)。如满足这两个条件就说明对象不会被回收,一直占有着内存空间。
下面给一个简单的内存泄漏的例子:
Vector v = new Vector();
for(int i=1;i<100;i++){
Object o = new Object();
v.add(o);
o = null;
}
所有的Object对象都没有被释放,因为v引用了这些对象。
整数溢出
当一个整数值大于或者小于其范围时,就会产生整数溢出。因为所有内置整数类型(char,short,int,long)都用一个固定的位数表示,所以其表示范围有限。当值超出最大或最小范围时,就会“回绕”。比如,一个非常大的整数变成一个负数。
比如下面一段程序模拟一个电子商务站点。从页面读取购买商品的数量,假定每个商品价值100元。
String numStr = request.getParamter("num");
int numInt = Integer.parseInt(numStr);
if(numInt > 0){
int total = numInt * 100;
}
如果攻击者提供一个足够大的商品数量,例如42949671。乘以100后就超过了带符号的32位整数所表示的范围,总价将会是-196。
避免整数溢出问题的最好方法是,检验所有的整数输入是否都位于上下界范围内。上下界的选择应当使得任何后续计算结果都不会超出所使用变量的容量限制。
java 定义了4个整数类型:字节型(byte),短整型(short),整型(int),长整型(long )。这些都是有符号的值,正数或是负数。Java 不支持仅仅是正的无符号的整数。
名称 | 类型 | 长度 | 范围 |
字符型 | char byte | 8 | -128 ~ 127 |
短整型 | short | 16 | –32,768 ~ 32,767 |
整型 | int | 32 | –2,147,483,648 ~ 2,147,483,647 |
长整型 | long | 64 | –9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 |