用户名: 密码: 免费注册 忘记密码? 网站地图 | 加入收藏 | 设为首页
首页 | 新闻 | 工具 | 系统 | 办公 | 聊天 | 多媒体 | 网页 | 运营 | 平面 | 欣赏 | 数据库 | 程序 | 服务器 | 组网
网页 | 3dmax | Ghost | Windows Xp| Dreamweaver | photoshop | Flash | office | Alexa | Css | QQ | Asp | PHP | Jsp | Access
Flash MX 2004入门 | 网站推广策略 | CorelDRAW入门 | ASP学习 | 网站建设大师功 | Word入门
  iTbulo.com > 学院 > 程序开发教程 > Perl应用教程 > PERL应用教程 > 文章正文
perl语言安全
iTbulo.COM 2006-4-26 佚名()
 
单引号
在perl中,另一种读取外部程序的输出的方法是把命令放在单引号里。所以如果我们想在分等级的$stats的文件中保存我们stats文件的内容的话,我们可以这样做:
$stats=’cat/user/stats/$username’;
这确实要通过shell层来实现。任何把用户输入包含在一对单引号内的脚本都有发生前面讨论的所有的安全问题的危险。有很多方法可试图使shell不要误解一席可能的转换字符。但是最安全的事就是不要用但引号。取而代之的是,打开一个通到STDIN的管道,然后分叉执行外部程序,就像我们在前一节open()所做的一样。


Eval()和/e 修饰符
函数eval()可以在运行时间执行一个Perl代码块,并返回上一次经评估语句的值。这种函数功能经常用于诸如配置文件,它可以写成perl代码,除非你绝对相信输进eval()的源代码,否则不要做诸如eval/$userinput,之类的事,这也适用于一个常规表述中的/e 修饰符,用来使perl在执行之前解释该表述。


过滤用户输入
用于本节我们所讨论的所有问题的过滤用户输入的一个通常方法(FU In OCA )就是过滤任何不需要的转换字符和有问题的数据。例如我们可以在任何时段过滤来避免向后的目录查看。类似的,我们一旦看见非法的字符,就让程序运行失败,这种策略被称为”黑名单”这种哲学就是如果某东西没有明确禁止,那它肯定是好的。一个更好的策略就”白名单”,它指如果某东西没有被明确认可,那么它必须禁止。黑明单的最重要的问题是它非常难保持完整性并得到更。你也许会忘掉过滤某一特定字符,或者你的程序或许不得不随不同的转换字符集合转到一个不同shell中。不过滤掉不需要的转换字符和其他危险输入,相反,只过滤进合法的输入。下面的片段就是一个例子,它会停止执行一个安全性有问题的*作,如果有户输入中包含了除字母,数字,点和@符号外任何东西(@经常用于用户的电子邮件地址)
unless($useradress=~/^[-@/w。]+)$/)

{print”secrity error。/n”exit(1);

}
基本的思想是不去编译一个特定值的列表来保护,而是产生一个安全列表来接受可接受的输入值的列表。可接受的输入输入值的选择当然会随着不同的应用程序而变化。可接受的值应该采用某种能将破坏的可能性降到最小的方式来选择。


避免shell
当然,你也必须尽可能的避免shell,然而这种技术可被广泛地应用。如果你调用一个有特定序列的编辑器。你必须确认这些特定序列是不被允许使用的。一般,通过使用现存perl模块,你能避免使用外部程序来执行一个外部函数,CPAN是一个能完成几乎所有标准UNIX工具集能做的任何事的经测试的函数的模块来源,然而它或许会费点劲来包含一个模块,并且调用它,而不是调用一个外部程序,模块方法一般来说更安全和灵活,为解释清楚这一点,使用Net::SMTP,而不用exec()’ing sendmail/--T会帮你少一些使用shell的麻烦,并能防止你的用户在sendmail代理中寻求已知的弱点。


其它安全问题的来源(不安全环镜变量)
用户输入实际上是perl程序的主要安全问题的来源,但是还有其它因素是在写安全的perl源代码时所必须考滤的,经常 在shell下运行的脚本的易受攻击的弱点或者通过网络服务器是不安全的环镜变量,最通常的是PATH /变量。当你从你代码内部中使用一个外部应用程序或功能,而仅仅指明了一条相对路径的时候,你就使 你这个程序和运行它的系统处于危险中。如果你有如下一个system()调用:
system(“txt2html”,”user/stats/jdiov”);
对于这种调用,你假设txt2htm文件是包含在PATH变量某处的目录下,但是假如发生这种情况,一个攻击者改变你的路径指向含有相同的名字的其他带恶意的程序中,你的系统的安全性就得不到保证。为了避免例似的事情发生,每个需要含有远程安全意识的程序都应该这样开始写:
#!/usr/bin/perl -wT

require 5.001;

use strict;

$ENV{PATH} = join ':' => split (" ", << '__EOPATH__');

/usr/bin

/bin

/maybe/something/else

__EOPATH__
如果程序依赖于其他环境变量,它们也要在它们使用前明确的定义出来。
另一个危险变量(这个更是针对perl的)是@INC距阵变量,它非常像PATH,只不过它 指明Perl到哪里去找要包含在程序中的模块。有关@INCR 的问题和PATH是非常相似的。有人可能会把你的perl指向一个具有相同的名字模块,而且如你所料的做同样的事,但是它也背地里做一些坏事,因此@INC同PATH都不值的信任。在包括任何外部模块之前都 必须完全重新定义。


Setuid脚本
通常一个Perl程序是以执行它的用户的权限来运行的。通过产生一个setuid脚本,它的有效用户的ID可以设定成更高的权限,这个权限使这个用户可以访问他实际没有访问权限的资源,比如passwd程序使用setuid来获取对系统password文件的写的权限,这样允许用户来更改自已的密码,因为执行程序是通过CGI界而来执行的,该界面是在使用网络服务器的用户权限下运行的,CGI程序员经常 试图使用setuid技巧来让他们的脚本执行一些恶作剧。这有可能用,但也可能十分危险,对一个事情,如果一个攻击者发现一各方法可以利用脚本的弱点他们不仅是获得访误问系统的权限,但是他们会用有效的UID的特权来获得存在着另外几种类似的种族状况,在一个程序当中,这类缺陷是比较容易监控的,尤其是对有经验的程序员来说,目前相关方面的工作正在积极的探索着。关于这个问题,目前还没有一个既容易又完全有效的解决方法,常常在种族状况存在的可能情况下,用到的最好的方法是使用原子*作方式来进行,这就意味着仅仅使用一种系统来同时检查和生存档案。而不必使用处理器,在二者之间进行切换。当然,这不可能是常有的。
另外我们所作的一种标准模式是使用SYSOPEN来确定一种只读模式,不必再设定删减标志。

通过这种方法,即使我们的文件名确实已经形成,当我们打开文件进行写*作的时候 ,我们也不会破坏文件。注意:Fcnt1模快必须包含进来,以便让sysopen()函数起作用,因为这个模块是如下常数,O_RDONLY, O_WRONLY, O_CREAT,等被定义的地方。


缓冲区溢出和perl
一般来说,perl脚本是不容易发生缓冲区溢出的,因为perl能在需要的时候动态的扩展它的数据结构。Perl跟踪为每个字符串分配的大小。在一个字符串每次被赋值之前,perl保证有足够的空间可以利用,如果需要的话,也可以为那个字符串分配更多的空间。
然而在一些较老的perl实现方法中有几种熟为人知的缓冲区溢出情形。一个明显的例子是5。003版本会因为缓冲区溢出而崩溃。所有的suidperl版本(一种设计用来工作在为某些内核)都是在早于5。004版本的perl的不同分类的基础上建立起来的。


结论:
在我们以后的文章中,我们将会化一定的时间来熟悉perl提供给我们的安全特性,尤其是perl的”taint 模式“,并且,我们将会证明,如果我们不小心的话,即使在如此坚固的安全机制下,依然可能会出现的一些问题。在学习perl的这些方面以及一些典型的例子的时候。我们的目标是为了培养我们的一种直觉,这种直觉能帮助我们在看perl脚本的第一眼时就能够意识到其中的安全问题,以避免在我们的程序中犯类似的错误。

上一页  [1] [2] 

文章搜索
相关资讯
相关文章 相关下载
优化你的 Perl 代码
Perl小技巧:文件操作
windows下Perl开发环境的安装和配置
mod_perl 编程的简单介绍
perl的建树算法
焦点信息