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的参数是什么都禁用
- 举个例子
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 进行许可。
        评论
    
    
        
            
    
    
        
    
