Linux系统安全_Sandbox

Sandbox沙箱在计算机领域中是一种程序隔离的机制,其目的则是限制不可信进程的权限。沙箱技术则常用于执行未经测试的或不可信的客户程序,(比如沙箱杀毒一类的),为了避免不可信程序可能破坏其他的程序运行,沙箱技术可以为不可信的程序提供虚拟化的磁盘,内存以及网络资源,而这又是对客户是透明的。

常规的安全机制则主要以降权来解决问题,但降权并不能带来真正的安全,sandbox也不能带来全方位的安全,沙箱机制结合多种系统安全技术来实现安全,从设计的理念上,打破传统的单一防御到纵深防御。

常规的纵深防御有六种常见的手法:

1 安全的编码(Secure Code),减少编写的错误。

2 应用技漏洞缓解技术(Application-level exploitation)(SSP,relro)

3 系统级漏洞缓解技术(System-level exploit mitigation)(ASLR,NX),

4 降权处理(Privilege Dropping)(Sandboxing)

5 强制访问控制(Mandatory access control)(MAC,SELinux)

6 更新策略(Update strategy)

 

进程和权限

         1 每个进程拥有独自的地址空间

         2 MMU硬件强制分离地址空间

         3 内核在系统中有强制性的接口层(kernel的安全策略)

         4 每个进程拥有进程权限边界

         5 root用户拥有至高的权限

         6 其他用户拥有自主访问控制DAC访问权限

一般情况下的权限控制为:

         进程A拥有的权能比进程B拥有的多,则A可以获得B进程可以访问的资源

         1 root用户运行任何程序都是特权用户

         2 2个进程如果拥有相同的uid,和gid。则可以拥有相同的权限

         3 一般不能比较不同uids用户的进程权限

进程和权限的分离

         1 线程

                   将内部特权进行分离(一般情况下)如NaCI,SECCOMP Sandbox

         2 Debugging

                 如果A进程可以Ptrace()B,那么A的权限要大于B的权限

 

 Linux标准的权限资源有

         1 Users,和 groups

                   1 uid,euid,suid,fsuid

                   2 gid,egid,sgid,fsgid,超级组

         2 POSIX.1e 权能

         3 Quota control

         4 Linux Container

         5 LSM(Linux Security Module)

 

Linux的权能划分了不同的权限单位

         如:CAP_NET_RAW: 允许使用RAW和PACKET Socket

                   CAP_SYS_ADMIN: 管理员操作权能(mount,sethostname等)

                   CAP_NET_BIND_SERVICE:bind绑定端口权限<1024

 

 权能的限制

         1 常见的误区:

                   1 忘记切换uid 为0的超级用户。很多功能需要root用户的权能

         2 root 操作

                   1 只有用到root权能的时候,才将权限提升为root权限

                   2 很多操作只需普通用户的权能。

使用切换root

1         需要对文件系统进行权限控制的时候,需要root用户

2         只有root可以操作的活动

3         需要一些陷入或escape的权限时,需要流行的chroot技术。

4         模块注入 非chroot进程的ptrace()

 

新的命名空间(Namespaces:CLONE_NEW*)

         CLONE_NEWPID: New pid namespace(2.6.24)

         CLONE_NEWNET:New network namsespace(2.6.26)

         CLONE_NEWIPC,CLONE_NEWUTS,CLONE_NEWNS(2.6.19)

 

资源限制

         为了安全的资源限制机制

         1 RLIMIT_NOFILE:不能获得新的句柄,但可以rename或者unlink

         2 RLIMIT_NPROC: 不能创建新的进程

         如果为了安全,RLIMIT_NPRC需要设置为(0,0),因为一些攻击者可以替代已经存在的句柄去创建新的socket或者文件句柄。

 

Dumpable(Debuggable)进程

         Linux支持对每个进程进行dumpable标志。

          通过PR_SET_DUMPABLE标记设置prctl,跟踪执行你没有权限的程序,或者切换uid。

          一个进程没有CAP_SYS_PTRACE权能,是不能ptrace非dumpable的进程

         需要一个进程权限提升或者可以降低其他进程的权限来满足dumpable。

 

MAC强制的访问控制

         在内核机制中,基于LSM钩子的有,SELInux,SMACK,TOMOYO

         内核机制之外的有:GRSecuirty, RSBAC, AppArmor

 

Sandbox 采取权限限制的策略

Sandbox与MAC的区别

         MAC需要管理员去分发布商。每个程序需要一套单独的规则库,不需要对代码的控制权

         Sandbox则是面向开发者,每个程序可以运行在多个设备上,不要要设备管理员的权限

 

常见的sandbox的设计:

         1 ptrace() sandbox (vsftpd)

         2       setuid sandbox(chromium)

         3      SECCOMP sandbox(chromium)

1 ptrace 架构:

setuid sandbox

 setuid sandbox基于Linux Kernel 所提供的安全机制如DAC实现,利用了uid/gid +  chroot()+capability的组合来达到目标,实现起来相对较为简单。

         传统的root 很难避免以下问题:1 需要对文件系统删除的访问2 RLIMIT_NOFILE 不够时的处理3  防止其他进程ptrace 4阻止信号发送给其他进程。

(一) Setuid :

利用uid的切换工作:

1我们需要获取uid/gid的定义池,但不需要资源/etc/passwd

2调用时,搜索到未用的uid/gid.然后切换到这个uid/gid

3执行sandbox。

Linux uid/gid 机制主要是用于进程的权限隔离,当你要执行不可信的程序时,那么在启动该程序的时,为其分配一个random uid。然后设置setuid。工作流程如下

Fork() ->setuid()->{设置相关的进程资源限制,如RLMIT_NPROC(0,)}->execve();

Setuid() 需要root的权限(或者具有CAP_SETUID 权能)才能调用成功。

 

(二) Chroot:

chroot 是 linux kernel 的另一个安全功能,他主要用于修改进程的根目录,比如执行chroot(“/tmp/sandbox/1”)则可以将当前进程的根目录切换为”/tmp/sandbox/1”。那么该进程的文件操作权限则被限制在当前目录下。

Chroot需要root权限(或者具有CAP_SYS_CHROOT权能)才能调用成功。

如果按照前面执行的顺序,具有root权限的进程A去执行chroot,然后再调用setuid,->..->execve(),这样是不可以的,因为execve所执行的路径已经发生改变,可执行文件已经不存在了。

Chris Evans的文章给了一个解决方法:

 

a) A创建一个子进程B,注意使用clone()和CLONE_FS,这样可以让A和B共享根目录,当前目录,等等

b)  A 降权去执行execve(“Worker”),B等待A进程发来的特殊消息.

c) 当A想执行chroot时,发送消息告知B。

d) B执行chroot(),新的根目录会对A和Worker同时生效

e) B退出。

对A程序来说,由于它是以Root身份运行,那么就可能作为攻击点,比如confuesed deputy问题。下面针对这个问题加以说明。

 

(三) Linux Capability

 主要解决confused deputy问题,这个问题典型的代表是跨站点请求伪造(CSRF)。

Linux支持Capability的主要目的则是细化root特权,避免confused deputy问题。比如ping这个命令,需要raw_sockets,所以需要root的权限才可以运行,如果有了Capablity机制,该程序只要一个CAP_NET_RAW的权能,便可以运行,根据最小权限原则,该程序可以去掉所有不必要的权能。

当前kernel支持的权能多大30多种。在kernel2.6.24以后,普通用户也具有了capability.

CAP_CHOWN                0    //允许改变文件的所有权

CAP_DAC_OVERRIDE         1    //忽略对文件的所有DAC访问限制

CAP_DAC_READ_SEARCH      2    //忽略所有对读,搜索操作的限制

CAP_FOWNER               3    //如果文件属于进程的UID,就取消对文件读限制

CAP_FSETID               4    //允许设置setuid位

CAP_KILL                 5    //允许对不属于自己的进程发送信号

CAP_SETGID               6    //允许改变组ID

CAP_SETUID               7    //允许改变用户ID

CAP_SETPCAP              8    //允许向其他进程转移能力以及删除其他进程读任意能力

CAP_LINUX_IMMUTABLE      9    //允许修改文件的不可修改(IMMUTABLE)和只添加(APPEND-ONLY)属性

CAP_NET_BIND_SERVICE     10   //允许绑定到小于1024读端口

CAP_NET_BROADCAST        11   //允许网络广播和多播访问

CAP_NET_ADMIN            12   //允许执行网络管理任务:接口/防火墙和路由等

CAP_NET_RAW              13   //允许使用原始(raw)套接字

CAP_IPC_LOCK             14   //允许锁定共享内存片段

CAP_IPC_OWNER            15   //忽略IPC所有权检查

CAP_SYS_MODULE           16   //插入和删除内核模块

CAP_SYS_RAWIO            17   //允许对ioperm/iopl

CAP_SYS_CHROOT           18   //允许使用chroot()系统调用

CAP_SYS_PTRACE           19   //允许跟踪任何进程

CAP_SYS_PACCT            20   //允许配置进程记账(process accounting)

CAP_SYS_ADMIN            21   //允许执行系统管理任务:加载/卸载文件系统,设置磁盘配额,开/关交换设备和文件等

CAP_SYS_BOOT             22   //允许重启系统

CAP_SYS_NICE             23   //允许提升优先级,设置其他进程的优先级

CAP_SYS_RESOURCE         24   //忽略资源限制

CAP_SYS_TIME             25   //允许改变系统时钟

CAP_SYS_TTY_CONFIG       26   //允许配置TTY设备

CAP_MKNOD                27   //允许使用mknod()系统调用

CAP_LEASE                28   //允许取消文件上的租借期

CAP_AUDIT_WRITE          29   //

CAP_AUDIT_CONTROL        30   //允许用户登录系统等

CAP_SETFCAP              31   //

CAP_MAC_OVERRIDE         32   //

CAP_MAC_ADMIN            33   //

CAP_TRUST_ADMIN          34   //

CAP_ALL                  **   //All Capability

0                        **   //no Capability

 

Setuid sandbox简单易行,在google chromuim  早期的沙箱机制中使用了它,但现在已经默认为seccomp机制了。利用ipc机制创建socket pair

Seccomp

Seccomp 是 Andrea Arcangeli在2005年设计的,其目的则是解决 grid computer中的安全问题,比如你打算租借cpu资源,但又担心不可信的代码会破坏你的系统,那么seccomp

则为你提供了一个“安全(SAFE,not SECURE)”的环境。

         内核从2.6.10开始引入seccomp机制,该机制限制系统调用为read(),write(),exit(),sigreturn(). 只有4个系统调用被允许,相对较为简单,其限制了不能分配内存,不能共享内存, 不能创建新的文件描述符。成为了一个纯计算型的代码。

  运行在seccomp机制下的线程成为可信线程,当不可信的线程请求可信线程进行系统调用时,可信线程验证后方可进行调用。可信线程也只能使用只读的存储器,不能读取可变的区域。

有人提出了对seccomp机制的改进,利用bitmap增加一个新的mode,来限制使用那些权能。

通过截获系统调用来实现sandbox是一贯的做法,在现在的操作系统中,用户空间和内核空间是隔离的,一个进程只能通过系统调用才能从用户空间进入内核空间,如果一个进程不执行系统调用,那么被攻击的风险便会降低。当然,不调用系统调用是不切合实际的。

针对chromium使用的sandbox机制,我们将接下来进行分析。

发表评论

您的电子邮箱地址不会被公开。