总结
- 这一次,主要解决与堆密切相关的漏洞
- 还有很多其他类型的漏洞
- 例如栈溢出,很有名并且很容易找到
- 条件竞争,整数溢出这类稍微有点难找
- 简单介绍一下其他漏洞
其他类型的漏洞
栈缓冲区溢出
- 当输入数据超出栈上分配的内存末尾时,会产生这种溢出
- 可以通过重写返回地址来控制后续操作
- 如果启用了canary保护,那么会检测到stack被更改
- 特别情况,仅能超出一个元素,被称为Off-By-One Stack Buffer Overflow。这种情况下只能重写ebp/rbp等,需要进行栈调整
堆缓冲区溢出
- 当输入的数据超出堆上分配的内存末尾时,会产生这种溢出
- 虽然不能重写返回地址,但是可以重写例如函数指针,数据等来控制后续操作
- 如果可以重写内存管理区域,则可以通过重写链表的next地址或者prev地址,向任意内存地址写入任意数据(之后会详细说明)
用户可控数据
- 这是导致溢出产生的现实原因,输入的数据由用户指定,而缓冲区是固定size,向固定size的缓冲区发送任意size的数据,就导致了溢出
- 这也能够导致Buffer Over Read
变更连接攻击(Unlink attack)
- 通过堆溢出,能够重写堆上的malloc管理数据(被称为chunk),通过free()的时候进行unlink处理,就更改了next或者prev到能够RWX的任意内存,可以写入任意数据
- 还可以进行GOT Overwrite
fastbins attack
- malloc/free时,可能进行fastbins attack
- malloc的返回地址能够任意指定,就产生了漏洞
字符串末尾NULL消除(Unterminated Null-Terminated String)
- C语言中的字符串是数组,如果没有结尾的NULL字符(=’\0’),那么在显示字符串时也会将后面的内容显示出来,造成信息泄漏
- 在这种情况下嘛,可以获得堆,栈,libc或者PIE的基地址,并且在某些情况下,可能泄漏例如用于加密/解密的密钥之类的重要信息
- 这可能是一个意外的长度,也会导致溢出
内存释放后的使用(Use After Free)
- 在malloc的内存被释放后,再次向该地址呢写入数据会发生这种情况
- 如果该地址已经被别的功能所使用,则可以重写改地址的数据
内存二次释放(Double Free)
- malloc申请的内存进行释放后,再次释放相同的地址
- 如果在第一次和第二次释放之间,这个地址被其他用途X获取到,那么第二次也会释放掉这个地址
- 那么,X在使用它时,堆中的数据可能会严重受损,因为它使用已经被释放的地址
类型混淆(Type Confusion)
- 在使用多种结构体/类的情况下,如果用户可以选择要应用的结构/类,错误的应用可能导致溢出及函数指针覆盖
格式化字符串漏洞(FSB: Format String Bug)
- 在printf系列函数中,如果使用printf(input)这类写法,攻击者就能够控制参数格式。正确的写法应该是printf(“%s”,input).
- 例如使用%p或者%x之类的转换说明符,可能泄漏stack上的值。即使是在ASLR/PIE环境下也可以置顶栈地址。
- 另外,如果用户输入在栈上,则可以输出该值地址,并以此为基础,向栈的内存地址写入数据
- 此外,%12345x这类指定字符宽度规范,可以自由指定printf输出的字符数。通过这个可能向任意内存地址写入任意值
- 覆盖stack或者GOT,重写数据或者函数指针,利用方式有很多
- FORTIFY_SOURCE(使用printf_chk之类的chk)情况下,无法使用%n
基于堆的FSB
- 格式化字符串攻击困难,用户输入不在stack上的情况
- 使用原本存在于stack上的二重引用(A→B→C)的指针,通过A修改B的低字节,通过B修改C,… 类似这样的攻略方式
条件竞争(Race Condition)
- 当资源管理对于竞争的处理不正确时,会发生这种情况
- 对一个对象同时进行多个操作,可能会导致该对象的状态出现问题
- 例如,在多人共享数据的服务中,客户端A和B同时连接的情况下,B在A打开某个文件的时候对该文件进行删除操作,类似这种情况
- 在某些情况下,数据可能被破坏,Use After Free或者Double Free,或者是堆溢出或栈溢出
TOCTOU条件竞争(Time-of-check Time-of-use Race Condition)
- 在A和B两次操作之间,因为另一个操作改变了状态
- 例如A[检查文件属性(确认它不是符号链接)],B[读取文件], 在A和B两次操作之间,文件被重写为符号链接,那么B将从符号链接读取内容
使用未初始化的数据(Using Uninitialized Variable)
- 使用之前已经被使用过的数据可能会导致意外操作
- 例如,申请的内存,未初始化的数据是”%p%p%p…”,如果未初始化直接使用printf将导致格式化字符串攻击之类的
负数处理问题
- 在条件比较情况中,没有正确考虑signed和unsigned的差异,从而将负数是别成大的正数的问题
- 它能够使得条件比较变得奇怪,以及更改指针索引等操作,也可能更改操作逻辑
整数溢出(Integer Overflow)
- 在32位数字和64位数字中,如果超出最大值或最小值,则会发生溢出。
- 例如,通过条件比较后故意溢出,可能导致申请很大的内存,或者使其很小
目录遍历
- 当二进制程序处理PATH时,可能被利用
- 使用
../../../../../proc/self/maps
之类的可以用于获取内存映射信息
其他Unlink经典题目
Plaid CTF 2014 – Pwnables200 –
ezhp
基本信息:
menu显示后,读取用户输入
可以输入1-4,使用jmp_table[idx]的形式调用对应函数
- 四个函数命名为add_note, remove_note, change_note, print_note
- add_note/remove_note有自己定义的malloc/free实现方式及堆管理
- 使用这样的结构体
1
2
3
4
5
6
7struct note {
unsigned int size;
note* next;
note* prev;
char* msg;
...
}- change_note有明显的溢出漏洞
- 可以通过重写next和prev来进行Unlink Attack
攻略方法:
这个二进制程序没有开启NX,服务器上开启了ASLR,这里有几种方法
- 通过Unlink让GOT指向堆chunk(与前面的babyfirst-heap相同的方式)
- 结合Unlink来泄漏堆值,写入GOT及jmp shellcode
- 结合Unlink,任意内存地址读写的方法
- 读取GOT的值,计算libc的偏移地址,加载system
- https://github.com/osirislab/CTF-Solutions/blob/master/PCTF_2014/ezhp/ezhp.py
- 通过Unlink将ppret加载到GOT并执行read(0, note[id], size)
- 返回note[id]将不通过read而通过ppret,也就能够执行shellcode
- https://pastebin.com/mEHQdcRW (只是有一定概率成功)
HITCON CTF 2014 Pwnables 550 –
stkof
基本信息:
- 读取用户输入
- 可以输入1-3,调用对应函数
- 三个函数命名为alloc_mem, write_mem, free_mem
- alloc_mem获得的地址,存储在bss上的PTR_TABLE[IDX++]中
- write_mem有明显的溢出问题
- 可以通过重写next, prev进行fastbins attack
攻略方法:
- 这个二进制程序启用了NX,ASLR,有两种之前提到的可用方法
- 通过覆盖chunk,让bss中存在的地址被认为是已经释放状态,故意创建了一个Use After Free情况,之后进行Unlink Attack
- 使用fastbins attack的简单解法
- 附加了详细解释
- http://pastebin.com/pwCxUE2V (fastbins attack)
- http://pastebin.com/3hiWVeNw (Unlink attack)
Hack.lu CTF Exploiting400 oreo
基本信息:
显示menu后,读取用户输入
可以输入1-5,调用对应函数
五个函数命名为Add_new_rifle, Show_added_rifles,Order_selected_rifles,Leave_a_Message_with_your_Order, Show_current_stats
使用这样的结构体:
struct RIFLE { char description[25]; char name[25]; char align[2]; RIFLE* next; }
Add_new_rifle有明显的溢出问题
可以通过覆盖next进行fastbins attack
攻略方法:
- 这个二进制程序启用了NX,ASLR
- 另外,使用了自定义的libc,无法猜测偏移量。攻略方法有三种
- 想办法找出自定义libc中system的偏移地址
- 使用ret2dl_runtime_resolve+DT_DEBUG
- 查找自定义libc中system的偏移量
- 猜测官方使用的是latest source构建的libc
- 从Gentoo Linux的每周Auto build的stage3.tar.bz2中获取libc,计算偏移量
- http://www.pastebin.com/9vq38BYH