文件权限
为什么需要权限
通过driver提供服务时,如果服务存在漏洞,用户可能会借此攻击服务器。比如访问driver所在主机上的任意文件,或是执行任意操作。 例如:使用driver实现了一个微型的http服务,然后访问文件时,输入了操作系统的路径,就可以访问到系统上的敏感文件;或是driver允许执行上传代码,也可以通过上传的代码执行系统指令。 同时,我们也不能简单的让driver限制脚本访问系统文件,执行系统命令,因为在某些情形我们需要这些功能。比如脚本archive_loader.gs,需要设置mount信息,这意味着它需要进行相关操作。 我们通过权限设置,可以选择在某些时段执行这些敏感调用,但是在某些时段禁止执行这些敏感调用。
权限的设置
限制权限有两种方式,一种是让不同的脚本有不同的权限,即按照使用者设置权限;另一个方式是让不同的时间有不同的权限,我们采用的是后者,即按照“时间段”来进行权限限制。我们使用这种方式的原因是控制更简单,使用者不容易出错。 目前我们权限仅有两阶,最高权限为ROOT(0),其次为USER(3)。 系统启动时权限为ROOT,然后可以通过os.set_euid()降低权限,需要注意,该函数只能进行降权,不能提权,这是为了避免有人上传恶意脚本自行提权。 某些必要的场合我们需要提权,比如单元测试脚本,运行时热更新可能会有此需求。可以通过os.reset_euid_to_root()实现,此命令需要传递一个密码,该密码是driver启动时通过--root-password来指明。为了避免某些管理人员偷懒造成攻击弱点,driver不设置默认密码,即如果启动时没有这个参数,无法在运行中提权。 权限的相关实现清参见cmm_privilege.h/cpp以及cmm_efun_os.cpp
关于osfile/osdir的后续改良
目前访问操作系统文件我们单独列出了一组函数,即osdir.,osfile.,这两组函数使用的文件路径是系统路径,而非脚本路径。 这个设计存在问题,一是函数臃肿(所有文件函数都有两套实现;二是底层的路径实现比较繁琐,现在driver底层代码在使用路径时,需要调用者清楚的知道相关接口的参数是哪种路径,同时还存在多次normalize path的导致降低效率的情况,因此我们考虑用一个class(比如Url)来封装文件路径,记录路径的相关信息(包括是否是系统路径、使用的协议、是否已经规范化),这样可以简化底层的实现。相应的,脚本代码也可以取消osdir/osfile这两类函数,而是直接使用Url结构封装。 原先的实现: osfile.read_all("/User/xxx/etc") 改良的实现: osfile.read_all(os.url("/User/xxx/etc")) 我们在处理权限判断时,只要再os.url()函数里进行判断即可,这样可以简化外部函数。