Board logo

标题: 安全编程 警惕输入 找出并保护程序的入口(1) [打印本页]

作者: look_w    时间: 2018-4-18 21:14     标题: 安全编程 警惕输入 找出并保护程序的入口(1)

如果您不控制,攻击者就会来控制安全的程序中第一道防线是检查每一个不可信的输入。但是这是什么意思呢?可以归结为以下三点:        
程序的类型决定一切您必须检查所有不可信的输入 —— 但是什么是不可信的输入呢?其中一些取决于您的程序要做什么。如果您的程序是数据的浏览器或者编辑器(比如文字处理器或者图像显示器),而这些数据有可能来自攻击者,所以那是不可信的输入。如果您的程序响应网络上的请求,那些请求可能正是来自攻击者 —— 所以网络连接是不可信的输入。
另一个重要的因素是您的程序是如何设计的。如果您的程序运行时身份是“root”或者其他一些特权用户,或者有对数据(比如数据库中的数据)的访问特权,那么从程序中没有特权的部分到那些有特权的部分的输入是不可信的。
尤其重要的情形是所有的“setuid”或者“setgid”的程序。只是运行一个 setuid/setgid 程序就会获得特权,这些程序特别难以保证安全。为什么呢?因为 setuid/setgid 程序有特别多的输入 —— 它们中很多输入多得惊人 —— 可以被攻击者控制。
常见的输入源下面的章节将讨论一些常见的输入以及如何处理这些输入。当您编写程序的时候这些输入每一个都应该考虑,如果它们不可信,一定要谨慎对它们进行过滤。
环境变量环境变量可能令人难以置信地危险,尤其是对那些 setuid/setgid 程序及它们调用的程序。危险的原因在于以下三个方面:        
有一些情形下,程序经过了修改,以使得难以利用它们来使用环境变量。历史上,很多攻击利用的是命令 shell 处理         IFS 环境变量的方法,但是当今大部分的shell(包括 GNU bash)已经经过了修改,从而使         IFS 难以利用。      
什么是IFS 问题?尽管现在已经不是一个严重的问题,但是           IFS 环境变量曾经在老的 Unix shell 中导致了很多安全问题。           IFS 用来确定命令中什么样的分隔词被发送到原始的Unix Bourne shell,并与其他环境变量一样被传递下去。通常           IFS 变量应该有一个空格、一个制表符和一个新行的值 -- 这些字符都会被作为一个空格字符来处理。但是攻击者可以将           IFS 设置为不怀好意的值,例如,他们可能向 IFS 添加一个“/”。这样,当shell 试图运行           /bin/ls 时,老的 shell 将把“/”解释为一个空格字符 -- 也就是说 shell 将运行“bin”程序(不管在哪儿找到一个),并使用“ls”选项!这样攻击者就可以提供一个程序可以找到的“bin”程序。        
值得欣慰的是,当今大部分的 shell 都对此进行了防范,当它们启动时至少会自动重新设置           IFS 变量-- 包括 GNU bash,GNU/Linux 常用的 shell。GNU bash 还限制了           IFS 的使用,使之只用于扩展的结果。这就意味着减少了           IFS 的使用,而且,这样危险度也大大降低了 (早期的sh 使用           IFS 来分离所有的词,甚至命令)。不幸的是,不是所有的 shell 都可以保护自己(          PracticalUnix & Internet Security-- 参阅 中的链接 -- 中有测试这一问题的样例代码)。尽管这一特定的问题已经(大部分)可以防范,但它仍以实例证明了没有经过检查的环境变量可以带来难以捉摸的问题。        

不幸的是,尽管这一加固措施是一个好主意,但它还是不够 —— 您还是需要谨慎地去处理环境变量。在 Unix 类系统上所有的程序如何运行,这是一个特别重要的(虽然难以理解)例子。Unix 类系统(包括 GNU/Linux)首先通过系统加载器来运行程序(在大部分 GNU/Linux 系统中这个加载器是 /lib/ld-linux.so.2),它可以定位并加载所需要的共享库。这个加载器通常由环境变量来控制。
在大部分 Unix 类系统中,加载器通常在环境变量         LD_LIBRARY_PATH 中列出的目录中开始搜索库。我应该说明一下,         LD_LIBRARY_PATH 被很多 Unix 类系统使用,但不是全部都用;HP-UX 用的是环境变量         SHLIB_PATH ,AIX 用的是         LIBPATH 。而且,在 GNU-based系统(包括 GNU/Linux)中,环境变量         LD_PRELOAD 所列出的库首先加载,并且优先于所有其他的库。      
问题是,如果攻击者可以控制程序用到的底层库,那么攻击者就可以控制整个程序。例如,假设攻击者可以运行 /usr/bin/passwd(一个可以改变您的口令的特权程序),但却用环境变量去改变这个程序用到的库。攻击者可以编写自己的口令加密函数crypt(3), 然后当特权程序尝试调用这个库时,攻击者可以让这个程序来做任何事情 —— 包括允许永久地、无限制地控制整个系统。当前,加载器通过检测程序是否设置了setuid/setgid 来防范这一问题,如果设置了,它们就会忽略         LD_PRELOAD 和         LD_LIBRARY_PATH 环境变量。      
那么,我们安全了吗?没有。如果恶意的         LD_PRELOAD 或者         LD_LIBRARY_PATH 值没有被 setuid/setgid 程序清除,它将被传递到其他程序,并导致出现加载器试图去防范的问题。因而,虽然加载器让编写安全的程序成为         可能,但您还不得不去防范恶意的环境变量。而且,这还不能处理那些没有文档化的环境变量的问题。      
对于安全的 setudi/setgid 程序来说,惟一可靠的办法是,始终在程序开始时“提取并清除”环境变量:





欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0