热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

安全编程:最小化特权根除软件的缺陷

文章标题:安全编程:最小化特权根除软件的缺陷。Linux是中国IT实验室的一个技术频道。包含桌面应用,Linux系统管理,内核研究,嵌入式系统和开源等一些基本分类

  安全的程序必须最小化特权,以降低 bug 转化为安全缺陷的可能性。本文讨论了如何通过最小化有特权的模块、授与的特权以及特权的有效时间来最小化特权。文章不仅讨论了一些传统的类 UNIX 特权机制,还讨论了较新的机制,如 FreeBSD 的 jail(), Linux 安全模块(Linux Security Modules,LSM)框架,以及 Security-Enhanced Linux(SELinux)。
  
  2003 年 3 月 3 日,Internet Security Systems 对 Sendmail 中的一个严重的漏洞提出了警告。所有的电子邮件都通过邮件传输代理(mail transfer agent,MTA)来传输,Sendmail 则是最流行的 MTA,所以这个警告影响了世界范围内的很多组织。问题在于,按通常的配置,精心设置了“from”、 “to”或者“cc”域的电子邮件消息可以让发送者完全(root)控制任何一台运行着 Sendmail 的机器。更严重的是,一般的防火墙将 不能 保护其内部的机器免受这种攻击。
  
  造成这一漏洞的直接原因是,Sendmail 的一个安全检测是有缺陷的,可以发生缓冲区溢出。不过,一个重要的作用因素是,Sendmail 经常被安装为一个单一的“setuid root”程序,对运行它的系统有完全的控制权限。这样,Sendmail 中的任何缺陷都可以让攻击者直接控制整个系统。
  
  这个设计是必须的吗?不是;Wietse Venema 的 Postfix 是一个常见的可以与之匹敌的 MTA。类似于 Sendmail,Postfix 会去做很多安全检测,不过,为了 最小化特权,Postfix 设计为一组模块。结果,Postfix 通常被认为是比 Sendmail 更安全的程序。本文讨论了如何最小化特权,您可以将同样的思想应用到您的程序中。
  
  最小化特权的基础
  实际应用的程序会有缺陷。不是我们希望那样,但是确实是有。复杂的需求、日程的压力和环境的变化使得不太可能得到实用的无缺陷的程序。甚至那些通过复杂而且精确的技术正式地证明是正确的程序,也会有缺陷。为什么?其中一个原因是,验证必须做很多假设,而且通常这些假设并不是完全正确。无论如何,出于种种原因,大部分程序没有得到严格的检验。而且,即使今天没有任何缺陷(不太可能),日后维护的改变或者环境的改变都可能会引入缺陷。所以,要处理实际的问题,我们不得不以某种方式来开发安全的程序, 尽管 我们的程序中有缺陷。
  
  尽管有这些缺陷,对安全编程来说最重要的方法是 最小化特权。特权只是允许去做并不是 每个人 都可以做的事情。在类 UNIX 系统中,拥有“root”用户、其他用户或者一个组的成员的特权是最常见的特权种类。一些系统让您可以授与读或写特定文件的特权。不过,不管怎么样,要最小化特权:
  
  只为程序中需要特权的部分授与特权
  只授与部分绝对需要的具体特权
  将特权的有效时间或者可以有效的时间限制到绝对最小
  这些其实是目标,不是绝对的。您的基础组织(比如您的操作系统或者虚拟机)可能使得严格完成这些并不容易,或者严格完成这些可能会很复杂,而导致在尝试严格完成时引入更多缺陷。但是,你距离这些目标越近,缺陷导致安全问题的可能性就越低。即使缺陷导致了安全问题,它导致的安全问题的严重性可能会更低。而且,如果您可以确保只有小部分程序拥有特定的特权,您就可以用大量额外的时间来确保 那 一部分能抵御攻击。这个思想并不新; Saltzer 和 Schroeder 的优秀的 1975 论文讨论了安全的原理,明确地将最小化特权作为一个原则(查看 参考资料)。有一些思想是永恒的,比如最小化特权。
  
  接下来的三节将依次讨论这些目标,包括如何在类 UNIX 系统中实现他们。然后,我们将讨论 FreeBSD 和 Linux 中可用的一些特别的机制,包括对 NSA 的 Security-Enhanced Linux(SELinux)的讨论。
  
  最小化有特权的模块
  如前所述,只有需要特权的部分程序才应用拥有特权。这就是说,当您设计您的程序时,尽量将程序分解为独立的部分,以使得只有小而独立的部分需要特定的特权。
  
  如果不同的部分必须同时运行,那么在类 UNIX 系统中使用进程(不是线程)。线程共享它们的安全特权,有问题的线程可能会干扰进程中所有其他线程。编写有特权的部分时,就当作其它的程序正在攻击它:某一天会可能!确保有特权的部分只去做尽可能少的事情;受限的功能意味着更不易被利用。
  
  一个通常的方法是,创建功能极度受限的拥有特定特权(比如是 setuid 或者 setgid)命令行工具。UNIX 的 passwd 命令就是一个例子;它是一个具有特定特权的命令行工具,用于修改密码(setuid root),但是它所能做的只是修改密码。于是各种 GUI 工具可以要求 passwd 来做实际的更改。如果有可能,尽量完全避免创建 setuid 或 setgid 程序,因为很难确保您正在真正保护所有输入。不过,有时您需要创建 setuid/setgid 程序,所以,当需要时,尽可能使程序最小且最受限制。
  
  有很多其他的方法。例如,您可以有一个具有特定特权的小的“服务器(server)”进程;那个服务器只允许特定的请求,而且只是在确认请求者被允许发出请求之后。另一个常见的方法是,使用特权启动一个程序,这个程序然后派生放弃所有特权的第二个进程,而由这个进程来做大部分工作。
  
  要当心这些模块彼此之间如何通信。在很多类 UNIX 系统上,命令行值和环境可以被其他用户看到,所以不是在进程间保密地发送数据的好办法。管道可以胜任,但是要细心地避免死锁(一个两端都可以刷新的简单的请求/响应协议就可以胜任)。
  
  最小化授与的特权
  确保您只授与特权给确实需要的程序——到此为止。UNIX 进行获得特权的主要途径是它们以哪个用户或组的身份运行。通常,进程以使用它们的用户和组身份运行,不过,“setuid” 或 “setgid” 的程序会获得拥有这个程序的用户或组的特权。
  
  悲哀的是,还是有一些不自主地给予程序“setuid root”特权的类 UNIX 系统上的开发者。这些开发者认为他们使得事情对自己来说变得“容易”,因为他们不必再去深入考虑他们的程序确切需要什么特权。问题是,由于这些程序程序可以在大部分类 UNIX 系统上做差不多所有的事情,所以任何一个缺陷都可以很快成为一个安全灾难。
  
  不要只是因为您需要完成一个简单的任务就给出所有可能的特权。而应该只给予程序它们所需要的特权。如果您可以,以 setgid 来运行它们,而不要用 setuid——setgid 给予的特权更少。创建特定的用户和组(不要使用 root),并根据您的需要使用它们。确保 root 所拥有的那些可执行程序只能由 root 来写,这样其他人就不能修改它们。设置非常严格的文件权限——如果不是绝对需要,不要让所有人都可以读或写文件,并且使用那些特定的用户和组。能说明所有这些的一个例子可能是游戏“top ten”分数的标准惯例。很多程序都是“setgid games”,以使得只有游戏程序可以修改“top ten”分数,而且存储这些分数的文件的主人是 games 组(而且只有这个组可以写)。即使攻击者攻击并进入了一个游戏程序,所有他能做的事情将是修改分数文件。无论如何,游戏开发者还是需要编写他们的程序来防止恶意的分数文件。
  
  chroot() 系统调用是一个实用的工具——不幸的是有一些难用。当进程查看文件系统的 “root”时,这个系统调用会修改进程所看到的内容。如果您计划用它——而且它可能是实用的——要准备好花一些时间来用好它。必须精心准备 “new root”,这是复杂的,因为确切的应用程序依赖于平台和应用程序的特性。您 必须 以 root 身份来进行 chroot() 调用,而且您 应该快速地 改变为非 root 身份(root 用户可以脱离 chroot 环境,所以如果它要生效,您需要解除那个特权)。而且 chroot 不会改变网络访问。这可以是一个实用的系统调用,所有有时候需要考虑它,但是要做好付出努力的准备。
  
  限制资源是一个经常被遗忘的工具,这既包括存储的资源也包括进程的资源。这些限制拒绝服务攻击尤其有用:
  
  对存储来说,您可以为每个用户或组设置每个挂载的文件系统的存储量或文件数的配额(限定)。在 GNU/Linux 系统中查看 quota(1)、quotactl(2) 和 quotaon(8) 来深入了解这一功能,不过,尽管它们不是哪里都能用,大部分类 UNIX 系统都包含了 quota 系统。在 GNU/Linux 和很多其他系统中,您可以设置“硬”界限(永远不能超出)和“软”界限(可以临时超出)。
  
  对进程来说,您可以设置很多限定,比如打开文件的数目、进程的数目,等等。这种能力实际上是标准的一部分(比如单一 UNIX 规范(Single UNIX Specification)),所有它们在类 UNIX 系统上几乎普遍存在;要深入了解,请查看 getrlimit(2)、 setrlimit(2) 以及 getrusage(2)、sysconf(3) 和 ulimit(1)。进程永远不能超出“当前界限”,但是它们可以将当前界限一路上升到“上限”。不幸的是,这里有一个不合常理的术语问题可能会使您迷惑。“当前界限”也被称为“软”界限,上限也称为 “硬”界限。这样,您就会处在一个异乎寻常的情形,进程 永远 不能超出进程界限的软(当前)界限——而对于 quota 来说您 可以 超出软界限。我建议为进程界限使用术语“当前界限”和“上限”(永远不要使用术语“软”和“硬”),那样就没有任何迷惑了。
  
  最小化特权的时间
  只是当需要的时候才给予特权——片刻也不要多给。
  
  只要可能,使用无论什么您立即需要的特权,然后 永久地 放弃它们。一旦它们被永久放弃,后来的攻击者就不能以其他方式利用那些特权。例如,需要个别的 root 特权的程序可能以 root 身份启动(比如说,通过成为 setuid root)然后切换到以较少特权用户身份运行。这是很多 Internet 服务器(包括 Apache Web 服务器)所采用的方法。类 UNIX 系统不允许任何程序打开 0 到 102
推荐阅读
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 本文介绍了在Hibernate配置lazy=false时无法加载数据的问题,通过采用OpenSessionInView模式和修改数据库服务器版本解决了该问题。详细描述了问题的出现和解决过程,包括运行环境和数据库的配置信息。 ... [详细]
  • 禁止程序接收鼠标事件的工具_VNC Viewer for Mac(远程桌面工具)免费版
    VNCViewerforMac是一款运行在Mac平台上的远程桌面工具,vncviewermac版可以帮助您使用Mac的键盘和鼠标来控制远程计算机,操作简 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
author-avatar
瀑布下的鱼
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有