什么是Off_By_One
一种特殊的漏洞,单字节溢出,即只能溢出一个字节数据。
off-by-one 漏洞原理
off-by-one,漏洞的产生与边界验证不严和字符串操作有关,其中边界验证不严通常包括
- 使用循环语句向堆块中写入数据时,循环的次数设置错误(这在 C 语言初学者中很常见)导致多写入了一个字节。
- 字符串操作不合适
例如
char buf[10]
for(int i=0;i<=10;i++)
{
buf[i]=getchar()
}
buff[i]=0
以上代码在一些c语言初学容易犯的错误,以为只输入了10字符(包括结束符),但实际却输入了11个字符,溢出了一个字符串结束标志符\00,这种也叫Off_By_unll。
或者
int main(void)
{
char buffer[40]="";
void *chunk1;
chunk1=malloc(24);
puts("Get Input");
gets(buffer);
if(strlen(buffer)==24)
{
strcpy(chunk1,buffer);
}
return 0;
}
由于strlen()函数识别\00截断,但返回的大小不包括\00,但在strcpy时会拷贝包括\00,所有实际拷贝了25个字符,导致Off_By_One。
利用方式
常见的利用方式:
- 溢出修改全局chunk指针的低位,来实现堆chuank的操作空间转移(转移到提前布置的伪造区域)
- 被溢出覆盖的数据二次重写后覆盖\00后如果有对数据的输入操作,可以实现数据泄露。
- 溢出修改chunk的size位可实现chunk extend,或unlink
但在 libc-2.29 之后
- 由于我们难以控制一个真实 chunk 的 size 字段,所以传统的 off-by-null 方法失效。但是,只需要满足被 unlink
的 chunk 和下一个 chunk 相连,所以仍然可以伪造 fake_chunk。