1. 操作系统安全问题
1.1 计算机感染恶意软件或被入侵
- 运行了恶意代码(email 附件, 下载并执行了 trojan 木马, 运行了受感染的硬盘)
- 运行了有 bug 的 daemon 程序(ftpd, httpd)
- 运行了有 bug 的客户端程序(web 浏览器, mail 客户端)
- 读取了有病毒和 bug 的文件
- 配置错误(弱口令,guest 帐户,DEBUG options,不正确的访问控制配置,etc)
1.2 原因
- 软件有漏洞(内存错误:缓冲区溢出、栈溢出、……)
- 漏洞会被利用
- 尽管有多层防御机制,但也会遭到破坏(没有一个安全机制是坚不可摧的)
- 安全问题的发生多是因为访问控制不当
1.3 UNIX 访问控制的一些问题
- 设计系统时仅考虑单机上的用户共享系统, 未考虑网络攻击和软件 bug
- 粗粒度:访问控制时取决于 user id;但该一个 user 可能运行多个程序(一些程序是不可信的),这些程序以同样的权限运行,如果每个程序拥有各自有限的权限会提高安全性
- root 功能太强大
1.4 解决方法
- 虚拟化限制
- 限制进程在有限空间内,不影响其它进程
- 三种虚拟化技术
- 细粒度的、基于进程的强制访问控制(Mandatory Access Control)
目的是更好的实现最小特权: 分配一个程序其需要的权限,不同于按用户进行权限划分
- root 权限分开
2. 虚拟化限制方法
2.1 操作系统级虚拟化
运行在单核下, 单操作系统上运行多个虚拟服务;服务提供者可以利用较低的代价提供主机服务。
- 优点:性能高,建立和管理比较容易
- 缺点:所有服务在单操作系统上,虚拟服务可能打破虚拟限制破坏操作系统
- chroot 系统调用: 改变当前进程和子进程到指定路径下的“根”目录,新的“根”目录(常称 jail)受真正的 root 的文件系统约束
- 一般的目录架构:
/
/bin
/sbin
/usr/bin
/home
- chroot 的目录架构:
/hell/
/hell/bin
/hell/sbin
/hell/usr/bin
/hell/home
- chroot 的作用
- 限制被 chroot 的使用者所能执行的程序,如 SetUid 的程序,或是会造成 Load 的 Compiler 等等
- 防止使用者存取某些特定文件,如 /etc/passwd
- 防止入侵者 /bin/rm -rf /
- 提供 Guest 服务
- 增进系统的安全
- 为一个运行的进程创建一个临时的 root 目录,并在新建的 root 目录中放入有限的应用
- chroot 的优点
- 增加了系统的安全性,限制了用户的权力:在经过 chroot 之后,在新根下将访问不到旧系统的根目录结构和文件,这样就增强了系统的安全性
- 建立一个与原系统隔离的系统目录结构,方便用户的开发:使用 chroot 后,系统读取的是新根下的目录和文件,这是一个与原系统根下文件不相关的目录结构。在这个新的环境中,可以用来测试软件的静态编译以及一些与系统不相关的独立开发程序
- 切换系统的根目录位置,引导 Linux 系统启动以及急救系统等:chroot 的作用就是切换系统的根位置,而这个作用最为明显的是在系统初始引导磁盘的处理过程中使用,从初始 RAM 磁盘 (initrd) 切换系统的根位置并执行真正的 init。另外,当系统出现一些问题时,我们也可以使用 chroot 来切换到一个临时的系统
- chroot 的缺点
- 仅 root 用户可运行 chroot:应防止用户将一个 setuid 程序(如, 一个假的 /etc/passwd 文件)放入一个特殊编制的 chroot 环境以避免受骗而获得高权限
- chroot 并非在所有系统上都完全安全:因为是 root 权限下的 chroot 环境,一旦攻破 chroot 会影响 root 安全
- chroot 环境也会影响其它进程和网络空间
- chroot 不能限制 I/O、带宽, 磁盘空间、CPU 时间等资源
- chroot 的一些原则
- 在chroot环境下以 non-root user 运行
- 正确的 “放弃” 权限
- 程序利用 saved uid 在 non-root user 和 root 用户切换
- 利用无歧义函数 setresuid() seteuid(), setreuid()
- 利用 chdir 显式进入 jail
- 在 jail 环境中内容尽量少
- 尽可能让 root 管理 jailed 文件
- 限制 jail 内文件和目录的权限
- 建立权限设置脚本
- 不要在 jail 环境存放 /etc/passwd 文件
- /etc/passwd 跟 CHROOT/etc/passwd 相同:被攻击者有机会得到 root 的 encrypted password;要保持 /etc/passwd 及 CHROOT/etc/passwd 的同步性是个大问题
- /etc/passwd 跟 CHROOT/etc/passwd 不同:可以把 CHROOT/etc/passwd 中的重要人物(如 root)的密码拿掉,然后以比较复杂的方法修改 /usr/bin/login
- 在建立 jail 环境前关闭文件描述符(在创建 jail 时,已打开的文件描述符能够通过 dup 被复制)
- chroot 配置了网络服务后,外部需要查看 chroot 环境的配置文件,从外部连接配置文件:
ln -s /chroot/named/etc/named.conf /etc/named.conf
(尽量让 root 管理配置文件,保持配置文件一致) - FreeBSD 系统下 Jail
- Jail 提供分散化的管理(partitioning), 与虚拟机相似
- Jail 内的限制因素
- 访问文件名空间时仅受限于 jail 内部
- 可限制绑定在指定 IP 地址下的网络资源
- 使用系统资源、执行特权操作能力大大减少
- 仅能与 jail 内其它进程交互
- FreeBSD jail 的三个目标
- 虚拟化: 每个 jail 是一个运行于单机的虚拟环境 ,拥有自己的文件、进程、用户、超级用户。在 jail 内部看起来和真实系统一样
- 安全: 每个 jail 和其他部分无关联,破坏其他部分比较困难
- 容易授权: 因为 jail 是受限环境, 管理员授权后对整个系统影响不大
- FreeBSD jail 缺点
- FreeBSD jail 并不是真正的虚拟化,不同于虚拟机,不能运行不同的操作内核版本,利用原操作系统内核进行上级配置 所有虚拟服务共享同一内核,可利用操作系统的bugs 和安全漏洞进行攻击 没有聚簇和进程迁移能力, 主机内核和主机系统的单点失效影响所有虚拟服务
- FreeBSD jail 安全
- FreeBSD jails 可有效增加服务安全性,因为jail 环境和其它部分是分离的
- 在网络管理方面,安全性相比 chroot 要高很多
- 对FreeBSD jail的限制:
- Jail 间进程不能互相干扰(ps 只能查看 jail 内进程)
- 禁止访问和加载模块以防修改正在运行的内核. 禁止修改多数 sysctrls 配置和安全级别
- 禁止修改网络配置, 包括接口和 IP 地址、禁止访问路由表。jail 仅能绑定指定 IP 地址,不可以修改防火墙规则
- 禁止 Mounting、unmounting 文件系统。不能访问 Jail 外的目录
- FreeBSD jail 优点
- 可在不同 jail 中安装不同的 daemon
- jail 内管理员授权方便
- jail内的超级用户具有有限特权 (如,不能修改防火墙规则)
- 很难越过jail环境,很难获得jail外系统环境信息
2.2 虚拟机
在用户进程中模拟硬件(模拟软件运行在主机 OS上,guest OS 运行在模拟软件上)
- 优点:不修改 OS,可直接运行多个 guest OS
- 缺点:性能差
2.3 虚拟指令集
- 无主机 OS, 一个小型的虚拟指令集运行在硬件上, 修改 guest OSes 后在上面运行
- 能使不同和不兼容的 OS 运行在同一台计算机上
- 优点:比虚拟机性能高;比操作系统级虚拟化支持多 OSes
- 缺点:每个 guest OS 需修改后才能运行(新 OS 版本需要打补丁)
3. root 权限划分
3.1 POSIX/Linux 内核能力
- Linux 内核将 root 权限分为多种能力
- CAP_CHOWN 0 :允许改变文件的所有权
- CAP_DAC_OVERRIDE 1 :忽略对文件的所有 DAC 访问限制
- CAP_DAC_READ_SEARCH 2 :忽略文件读及目录搜索的 DAC 访问限制
- CAP_FOWNER 3 :忽略文件属主 ID 必须和进程用户 ID 相匹配的限制(最后操作的UID会覆盖文件的先前的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(只添加)属性标志
- CAP_NET_BIND_SERVICE 10 :允许绑定到 1024 以下的 TCP/UDP sockets 和 32 以下的 ATM VCIs
- CAP_NET_BROADCAST 11 :允许广播,监听多播
- CAP_NET_ADMIN 12 :允许执行网络管理任务
- CAP_NET_RAW 13 :允许使用原始套接字
- CAP_IPC_LOCK 14 :允许锁定共享内存片段
- CAP_IPC_OWNER 15 :忽略 IPC 所有权检查
- CAP_SYS_MODULE 16 :允许插入和删除内核模块
- CAP_SYS_RAWIO 17 :允许直接访问 /devport,/dev/mem,/dev/kmem 及原始块设备
- CAP_SYS_CHROOT 18 :允许使用 chroot() 系统调用
- CAP_SYS_PTRACE 19 :允许跟踪任何进程
- CAP_SYS_PACCT 20 :允许执行进程的 BSD 式审计
- 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 :允许修改文件锁的 FL_LEASE 标志
- 实现能力集要求:
- 对所有特权操作,内核必须检查进程的能力位是否 effective
- 内核提供相应的系统调用,进程获得或改变能力集
- 文件系统应支持可执行文件与相应的能力集相对应,使得可执行文件运行时获得对应的能力
- 进程的能力表示:每个进程有三个能力集
- effective :进程进行某个特权操作时,操作系统检查 cap_effective 的对应位是否有效,而不再是检查进程的有效 UID 是否为0
- permitted :表示进程能够使用的能力,这些能力是被进程自己临时放弃的, cap_effective 是 cap_permitted 的一个子集
- inheritable :加载新进程时可继承的能力
- 可执行文件的能力表示:可执行文件的能力集如下
- allowed(inheritable) :可继承的能力
- forced(permitted) :可获得的能力
- transfer(effective) :从 permitted 转化为 effective 的能力
- 能力边界集:能力边界集(capability bounding set)是系统中所有进程允许保留的能力
- 系统调用接口:系统调用 capset 和 capget 设置和获得进程能力
- 内核中能力的安全作用
- 程序可以使用 root 的部分特权,而不需要该程序 setuid root :程序的 forced 能力位置 1 即可
- 系统引导时删除部分能力,会保护系统
保护系统工具和日志的完整性
- CAP_LINUX_IMMUTABLE 能力,允许修改文件的 IMMUTABLE 和 APPEND 属性标志
- 去除 CAP_LINUX_IMMUTABLE 能力,攻击者不能删除其攻击轨迹、不能安装后门工具、系统日志文件为 append-only、系统工具不被删除和修改
3.2 FreeBSD 安全级
- 安全模式
-1 : Permanently insecure mode 0 : Insecure mode 1 : Secure mode 2 : Highly secure mode 3 : Network secure mode
- 在内核中执行安全级
- 当安全级 > 0,内核限制执行某些操作;superuser 也不能执行限制操作
- 不能降低正在运行系统的安全级
- 要降低安全级, 需要修改 /etc/rc.conf 中的安全级配置并需重启
- FreeBSD FAQ的安全级警告
- 安全级并非坚不可摧; 也有很多缺陷. 经常导致安全问题
- 一个最大的安全问题: 在系统引导时设置所有文件的安全级,设置安全级后安全级才能起作用。当攻击者在设置安全级之前能够执行代码,则所有后续保护都失效。
4. 细粒度的强制访问控制
4.1 细粒度访问控制思想
- 每个进程, 都有相应的策略控制该进程可以做什么
- 不同于自主访问控制,自主访问控制权限取决于 user id
- 具体指明其能力,访问具体文件的权限
- 控制策略的执行时间
- 加载二进制代码时
- 进程获得数据时
- 困难性
如何指定策略
4.2 细粒度访问控制工具
- Systrace
- Linux的入侵检测系统 (LIDS)
4.3 安全增强的 Linux (SELinux)
- SELinux提供了比传统的UNIX权限更好的访问控制
- 管理员可以只允许一个应用程序添加记录到一个日志文件,但不允许其修改或者删除该日志文件的内容
- 一个应用程序可以被允许在一个文件夹中建立文件和向其写入数据,但不能删除文件:这种特性是没有SELinux的普通的Linux内核所不能做到的
- 网络应用程序可以绑定到其需要的端口上(如 BIND 的 53 端口),但不能绑定其它端口
- 域-类型
- 模型意味着在安全域中运行着的每一个进程和每一个资源(一般文件、目录文件和套接字等)都有一个与之相联系的“类型”(type)
- 在域-类型上建立了一系列规则,这些规则列出了某个域可以在每一个类型上执行的所有动作
- 进程的上下文组成
SELinux 的系统中,每一个进程的上下文都包含三个组成部分:一个ID(identity),一个角色(role)和一个域(domain)
- ID:用户,进程的所有者,系统进程 ID(system_u) ,未知用户进程 ID(user_u)
- 角色用来判断某个处于此角色的ID可以进入哪些域,还用来防止某个处于此角色的ID进入其它不该进入的域(比如,user_r 角色就不允许进入 sysadm_t)
- 一个安全上下文可以像 identity:role:domain(可用 ps 和 ls 查看)
4.4 SELinux 细粒度访问控制
- 类型强制访问控制——TE(type enforce)
- 所有访问都必须明确授权,SELinux 默认不允许任何访问,不管 Linux 用户/组 ID 是什么。即在 SELinux 中,没有默认的超级用户
- 与标准 Linux 中的 root 不一样,通过指定主体类型(即域)和客体类型使用 allow 规则授予访问权限
- allow规则由四部分组成:
- 源类型(Source type(s)):尝试访问的进程的域类型
- 目标类型(Target type(s)):被进程访问的客体的类型
- 客体类别(Object class(es)):指定允许访问的客体的类型
- 许可(Permission(s)):象征目标类型允许源类型访问客体类型的访问种类
- allow user_t bin_t : file {read execute getattr}
- 源类型(或主体类型或域)user_t
- 目标类型(或客体类型)bin_t
- 标识符file是定义在策略中的客体类别名称
- 大括号中包括的许可是文件客体类别有效许可
- 举例:
- passwd 程序是可信任的,修改存储经过加密的密码的影子密码文件(/etc/shadow)
强制访问控制:确保只有passwd程序(或类似的受信任的程序)可以访问shadow文件,不管运行程序的用户是谁
- 查看文件域属性:
# ls -Z /etc/shadow
-r---- root root system_u:object_r:shadow_t shadow
- 查看进程域属性:
# ps -aZ
joe:user_r:passwd_t 16532 pts/0 00:00:00 passwd
- allow 规则:授予 passwd 进程的域类型(passwd_t)访问 shadow 的文件类型(shadow_t),允许进程移动并创建一个新的 shadow 密码文件
- 普通用户修改密码过程