Off by one overflow
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
仅仅访问1B溢出允许攻击者修改下一个块的size
字段。这允许篡改哪些块实际上被释放,可能生成一个包含另一个合法块的块。利用这种漏洞的方式类似于double free或重叠块。
有两种类型的off by one漏洞:
任意字节:这种类型允许用任何值覆盖该字节
空字节(off-by-null):这种类型仅允许用0x00覆盖该字节
这种漏洞的一个常见示例可以在以下代码中看到,其中strlen
和strcpy
的行为不一致,这允许在下一个块的开头设置一个0x00字节。
这可以通过House of Einherjar进行利用。
如果使用Tcache,这可以被利用为double free情况。
在其他检查中,现在每当一个块被释放时,都会将前一个大小与元数据块中配置的大小进行比较,这使得从版本2.28开始,这种攻击相当复杂。
由于使用了Tcaches,这种攻击不再有效。
此外,如果您尝试使用更大的块进行滥用(因此不涉及tcaches),您将收到错误:malloc(): invalid next size (unsorted)
使一个块包含在另一个块内,因此对第二个块的写入访问允许覆盖包含的块
通过一个溢出修改大小元数据
分配三个块 A
、B
和 C
(假设大小为0x20),以及另一个块以防止与顶块合并。
释放 C
(插入到0x20 Tcache空闲列表中)。
使用块 A
溢出到 B
。利用越界修改 B
的 size
字段从0x21到0x41。
现在我们有 B
包含空闲块 C
释放 B
并分配一个0x40的块(它将再次放置在这里)
我们可以修改 C
的 fd
指针,它仍然是空闲的(Tcache中毒)
依次保留3个内存块(a、b、c)。然后释放中间的一个。第一个块包含一个越界溢出漏洞,攻击者利用它写入0x00(如果前一个字节是0x10,它将使中间块指示它比实际小0x10)。
然后,在中间释放的块(b)中分配两个更小的块,但是,由于 b + b->size
从未更新 c 块,因为指向的地址小于它应该的值。
然后,b1和c被释放。由于 c - c->prev_size
仍然指向 b(现在是 b1),两者合并为一个块。然而,b2仍然在 b1 和 c 之间。
最后,执行新的 malloc,回收这个内存区域,实际上将包含 b2,允许新 malloc 的所有者控制 b2 的内容。
这张图片完美地解释了这个攻击:
由于 strlen
考虑下一个块的 size
字段而导致的越界。
使用了Tcache,因此一般的越界攻击可以通过Tcache中毒获得任意写入原语。
可以利用越界泄露堆中的地址,因为字符串末尾的字节0x00被下一个字段覆盖。
通过滥用越界写入使指针指向另一个地方,在那里将构建一个带有假指针的假结构。然后,可以跟随这个结构的指针以获得任意写入。
libc地址被泄露,因为如果使用mmap扩展堆,mmap分配的内存与libc有固定的偏移量。
最后,滥用任意写入将写入到 __free_hook 的地址,使用一个 gadget。
在读取用户输入行的 getline
函数中存在一个NULL越界漏洞。此函数用于读取内容的“密钥”,而不是内容。
在写作中创建了5个初始块:
chunk1 (0x200)
chunk2 (0x50)
chunk5 (0x68)
chunk3 (0x1f8)
chunk4 (0xf0)
chunk defense (0x400) 以避免与顶块合并
然后释放块1、5和3,因此:
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]