Seccomp学习(1)
前言
- 也算打了蛮多比赛,每次比赛都会有沙箱
Sandbox
,每次都去上网查资料,这次整理一下各种资料,尽量完善一下关于这方面的知识点。 - 这里只介绍linux中的
Seccomp
- 本部分只是基础介绍一下什么是
Seccomp
以及相关的指令
参考文章:this
介绍
- 先来了解一下什么是沙箱保护
Seccomp(Secure Computing Mode) 是 Linux 内核提供的一种安全机制,允许进程在运行时限制自己能够调用的系统调用。通过这种机制,Seccomp 可以显著降低攻击面,防止恶意进程执行危险的系统调用或造成资源泄露。
- 也就是说
Seccomp
会过滤掉它所规定的指令,当用户执行这些指令的时候会被限制,不允许执行,下面让我们简单写一段代码看看
注意:为了使用seccomp头文件要安装下面所需:
1 | sudo apt install libseccomp-dev libseccomp2 seccomp |
测试程序
未开启沙箱
1 | gcc -g no_seccomp_execve.c -o no_seccomp_execve -lseccomp |
- 执行效果:
开启沙箱
1 | //gcc -g seccomp_execve.c -o seccomp_execve -lseccomp |
- 执行效果:直接报错
分析
- 对比两段代码,第一个是没有开启沙箱禁用
execve
,此时随便执行什么都可以。
补充知识:
ctx
:是一个指向 Seccomp 过滤器上下文 的指针,它是seccomp_init
函数返回的一个结构体
ctx = seccomp_init(SCMP_ACT_ALLOW)
其中的SCMP_ACT_ALLOW
表示初始化时默认允许所有的系统调用
- 第二个开启了沙箱,禁用了
execve
,所以当我们试图去调用execve
的时候会报错
详细解释一下seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0)
使用
seccomp_rule_add()
来向过滤器上下文中添加规则,规定特定的系统调用行为
通过
seccomp_load()
将已配置好的过滤器上下文加载到进程中,开始生效。
后面的0表示
execve
的参数,也就是说无论execve的参数是什么都禁用
- 举个例子
1
2
3
4
5
6
7
8
9
10
11
12
13
int main(void){
scmp_filter_ctx ctx;
ctx = seccomp_init(SCMP_ACT_ALLOW);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(write),1,SCMP_A2(SCMP_CMP_GT,0x10));//第2(从0)个参数大于0x10
seccomp_load(ctx);
write(1,"i will give you a shell\n",24);//会拦截
write(1,"1234567812345678",0x10);//不被拦截
return 0;
}
- 执行效果:
第一部分为注释掉第一条write,第二部分未注释
工具
seccomp-tools
:下载地址:this
- 效果
Prtctl简介
关于这部分感兴趣的直接看开头的参考文章即可,这里只讲Seccomp
简单例题(orw)
源码
1 | // gcc -g orw.c -o orw -lseccomp -fno-stack-protector -no-pie -z execstack |
分析
1 | pwn@ctfpwn:~/learn/Seccomp/test$ seccomp-tools dump ./orw |
- 禁用了
execve
,我们无法直接写execve的shellcode去get shell,但难道没有其他方法了吗? - 这道题目就是经典的
orw
,open
读flag,read
将其储存到buf,最后write
输出出来,这道题目就可以直接打orw
,先布置好shellcode
然后jmp到rsp再执行shellcode - 方法参考:这篇文章
EXP
1 | from pwn import * |
- 效果:
手写汇编
- 先介绍一下三个函数的系统调用(64位情况下)
open
系统调用用于打开一个文件,并返回文件描述符。系统调用号: 2
寄存器传递参数:
rax
= 2(open
的系统调用号)rdi
= 文件路径(const char *pathname
)rsi
= 标志(int flags
,例如O_RDONLY
、O_WRONLY
、O_RDWR
等)rdx
= 模式(mode_t mode
,用于O_CREAT
标志时指定文件权限)
read
系统调用用于从文件描述符读取数据。系统调用号: 0
寄存器传递参数:
rax
= 0(read
的系统调用号)rdi
= 文件描述符(int fd
)rsi
= 缓冲区(void *buf
)rdx
= 要读取的字节数(size_t count
)
write
系统调用用于向文件描述符写入数据。系统调用号: 1
寄存器传递参数:
rax
= 1(write
的系统调用号)rdi
= 文件描述符(int fd
)rsi
= 缓冲区(const void *buf
)rdx
= 要写入的字节数(size_t count
)
1 | shellcode = ''' |
- 标题: Seccomp学习(1)
- 作者: D0wnBe@t
- 创建于 : 2024-11-13 20:29:34
- 更新于 : 2024-11-14 13:05:00
- 链接: http://downbeat.top/2024/11/13/Seccomp学习-1/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论